mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 13:47:19 +08:00
feat: use retry decorator instead of retrying in a loop (#2058)
* feat: use retry decorator instead of retrying in a loop * update code logic * update poetry lock
This commit is contained in:
@@ -11,6 +11,7 @@ from glob import glob
|
||||
|
||||
import docker
|
||||
from pexpect import exceptions, pxssh
|
||||
from tenacity import retry, stop_after_attempt, wait_fixed
|
||||
|
||||
from opendevin.core.config import config
|
||||
from opendevin.core.const.guide_url import TROUBLESHOOTING_URL
|
||||
@@ -357,52 +358,44 @@ class DockerSSHBox(Sandbox):
|
||||
environment=self._env,
|
||||
)
|
||||
|
||||
def start_ssh_session(self, n_retries=5):
|
||||
while n_retries > 0:
|
||||
try:
|
||||
self.ssh = pxssh.pxssh(
|
||||
@retry(stop=stop_after_attempt(5), wait=wait_fixed(5))
|
||||
def __create_ssh(self):
|
||||
try:
|
||||
return pxssh.pxssh(
|
||||
echo=False,
|
||||
timeout=self.timeout,
|
||||
encoding='utf-8',
|
||||
codec_errors='replace',
|
||||
)
|
||||
break
|
||||
except pxssh.ExceptionPxssh as e:
|
||||
logger.exception(
|
||||
'Failed to start SSH session, retrying...', exc_info=False
|
||||
)
|
||||
n_retries -= 1
|
||||
if n_retries == 0:
|
||||
raise e
|
||||
time.sleep(5)
|
||||
except pxssh.ExceptionPxssh as e:
|
||||
logger.exception(
|
||||
'Failed to create SSH session, retrying...', exc_info=False
|
||||
)
|
||||
raise e
|
||||
|
||||
# Use the retry decorator, with a maximum of 5 attempts and a fixed wait time of 5 seconds between attempts
|
||||
@retry(stop=stop_after_attempt(5), wait=wait_fixed(5))
|
||||
def __ssh_login(self, hostname, username, ssh_password, ssh_port):
|
||||
try:
|
||||
self.ssh.login(
|
||||
hostname, username, ssh_password, port=ssh_port
|
||||
)
|
||||
except pxssh.ExceptionPxssh as e:
|
||||
logger.exception(
|
||||
'Failed to login to SSH session, retrying...', exc_info=False
|
||||
)
|
||||
raise e
|
||||
|
||||
def start_ssh_session(self):
|
||||
self.ssh = self.__create_ssh()
|
||||
hostname = self.ssh_hostname
|
||||
if self.run_as_devin:
|
||||
username = 'opendevin'
|
||||
else:
|
||||
username = 'root'
|
||||
username = 'opendevin' if self.run_as_devin else 'root'
|
||||
logger.info(
|
||||
f'Connecting to {username}@{hostname} via ssh. '
|
||||
f"If you encounter any issues, you can try `ssh -v -p {self._ssh_port} {username}@{hostname}` with the password '{self._ssh_password}' and report the issue on GitHub. "
|
||||
f"If you started OpenDevin with `docker run`, you should try `ssh -v -p {self._ssh_port} {username}@localhost` with the password '{self._ssh_password} on the host machine (where you started the container)."
|
||||
)
|
||||
|
||||
# TODO there's a similar block nearby, replace with some retry decorator instead or something
|
||||
n_retries = 5
|
||||
while n_retries > 0:
|
||||
try:
|
||||
self.ssh.login(
|
||||
hostname, username, self._ssh_password, port=self._ssh_port
|
||||
)
|
||||
break
|
||||
except pxssh.ExceptionPxssh as e:
|
||||
logger.exception(
|
||||
'Failed to login to SSH session, retrying...', exc_info=False
|
||||
)
|
||||
n_retries -= 1
|
||||
if n_retries == 0:
|
||||
raise e
|
||||
time.sleep(5)
|
||||
self.__ssh_login(hostname, username, self._ssh_password, self._ssh_port)
|
||||
|
||||
# Fix: https://github.com/pexpect/pexpect/issues/669
|
||||
self.ssh.sendline("bind 'set enable-bracketed-paste off'")
|
||||
@@ -424,10 +417,10 @@ class DockerSSHBox(Sandbox):
|
||||
return bg_cmd.read_logs()
|
||||
|
||||
def _send_interrupt(
|
||||
self,
|
||||
cmd: str,
|
||||
prev_output: str = '',
|
||||
ignore_last_output: bool = False,
|
||||
self,
|
||||
cmd: str,
|
||||
prev_output: str = '',
|
||||
ignore_last_output: bool = False,
|
||||
) -> tuple[int, str]:
|
||||
logger.exception('Command timed out, killing process...', exc_info=False)
|
||||
# send a SIGINT to the process
|
||||
@@ -442,7 +435,7 @@ class DockerSSHBox(Sandbox):
|
||||
)
|
||||
|
||||
def execute(
|
||||
self, cmd: str, stream: bool = False, timeout: int | None = None
|
||||
self, cmd: str, stream: bool = False, timeout: int | None = None
|
||||
) -> tuple[int, str | CancellableStream]:
|
||||
timeout = timeout or self.timeout
|
||||
commands = split_bash_commands(cmd)
|
||||
|
||||
2
poetry.lock
generated
2
poetry.lock
generated
@@ -7548,4 +7548,4 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.11"
|
||||
content-hash = "70be72e8064824ea756bf2543c8588e266a980e0e6dbc1fc50eecfb365c707d9"
|
||||
content-hash = "05410bbac602e5b5a91986d9f58c06bab86f63a87ffa62f5e52de94b472a1910"
|
||||
|
||||
@@ -32,6 +32,7 @@ boto3 = "*"
|
||||
minio = "^7.2.7"
|
||||
gevent = "^24.2.1"
|
||||
pyarrow = "16.1.0" # transitive dependency, pinned here to avoid conflicts
|
||||
tenacity = "^8.3.0"
|
||||
|
||||
[tool.poetry.group.llama-index.dependencies]
|
||||
llama-index = "*"
|
||||
@@ -66,6 +67,7 @@ reportlab = "*"
|
||||
concurrency = ["gevent"]
|
||||
|
||||
|
||||
|
||||
[tool.poetry.group.evaluation.dependencies]
|
||||
streamlit = "*"
|
||||
whatthepatch = "*"
|
||||
|
||||
Reference in New Issue
Block a user