简化重试函数
This commit is contained in:
parent
7eb8655724
commit
23c1109cae
6 changed files with 100 additions and 109 deletions
|
@ -18,45 +18,49 @@ from mower.utils.device.method.mumu_ipc import (
|
||||||
)
|
)
|
||||||
from mower.utils.device.method.scrcpy import Scrcpy
|
from mower.utils.device.method.scrcpy import Scrcpy
|
||||||
from mower.utils.device.simulator import restart_simulator
|
from mower.utils.device.simulator import restart_simulator
|
||||||
from mower.utils.device.utils import RETRY_TRIES, retry_sleep
|
|
||||||
from mower.utils.image import bytes2img
|
from mower.utils.image import bytes2img
|
||||||
from mower.utils.log import logger, save_screenshot
|
from mower.utils.log import logger, save_screenshot
|
||||||
|
|
||||||
|
|
||||||
|
def retry_adb(func):
|
||||||
|
@wraps(func)
|
||||||
|
def retry_wrapper(self, *args, **kwargs):
|
||||||
|
for attempt in range(2):
|
||||||
|
try:
|
||||||
|
return func(self, *args, **kwargs)
|
||||||
|
except MowerExit:
|
||||||
|
raise
|
||||||
|
except ADBError as e:
|
||||||
|
logger.warning(f"ADB error, retrying... ({attempt + 1}/3)")
|
||||||
|
logger.exception(e)
|
||||||
|
self.adb.adb_reconnect()
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception(e)
|
||||||
|
# After adb retries fail, escalate to simulator error
|
||||||
|
raise SimulatorError("ADB failed after 2 attempts.")
|
||||||
|
|
||||||
|
return retry_wrapper
|
||||||
|
|
||||||
|
|
||||||
def retry(func):
|
def retry(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def retry_wrapper(self, *args, **kwargs):
|
def retry_wrapper(self, *args, **kwargs):
|
||||||
init = None
|
for attempt in range(2):
|
||||||
for _ in range(RETRY_TRIES):
|
|
||||||
try:
|
try:
|
||||||
if callable(init):
|
|
||||||
retry_sleep(_)
|
|
||||||
init()
|
|
||||||
return func(self, *args, **kwargs)
|
return func(self, *args, **kwargs)
|
||||||
except MowerExit:
|
except MowerExit:
|
||||||
break
|
raise
|
||||||
except SimulatorError as e:
|
|
||||||
logger.exception(e)
|
|
||||||
|
|
||||||
def init():
|
|
||||||
restart_simulator()
|
|
||||||
except GameError as e:
|
except GameError as e:
|
||||||
|
logger.warning(f"Game error, retrying... ({attempt + 1}/2)")
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
|
self.check_current_focus()
|
||||||
def init():
|
except SimulatorError as e:
|
||||||
self.check_current_focus()
|
logger.warning(f"Simulator error, retrying... ({attempt + 1}/2)")
|
||||||
except ADBError as e:
|
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
|
restart_simulator()
|
||||||
def init():
|
|
||||||
self.adb.adb_reconnect()
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
|
restart_simulator()
|
||||||
def init():
|
|
||||||
pass
|
|
||||||
|
|
||||||
logger.error(f"Retry {func.__name__}() failed")
|
|
||||||
raise MowerExit
|
raise MowerExit
|
||||||
|
|
||||||
return retry_wrapper
|
return retry_wrapper
|
||||||
|
@ -85,7 +89,6 @@ class Device:
|
||||||
def run(self, cmd: str) -> Optional[bytes]:
|
def run(self, cmd: str) -> Optional[bytes]:
|
||||||
return self.adb.adb_shell(cmd)
|
return self.adb.adb_shell(cmd)
|
||||||
|
|
||||||
@retry
|
|
||||||
def launch(self) -> None:
|
def launch(self) -> None:
|
||||||
"""launch the application"""
|
"""launch the application"""
|
||||||
logger.info("明日方舟,启动!")
|
logger.info("明日方舟,启动!")
|
||||||
|
@ -101,13 +104,11 @@ class Device:
|
||||||
f"monkey --pct-syskeys 0 -p {config.conf.APPNAME} -c android.intent.category.LAUNCHER 1"
|
f"monkey --pct-syskeys 0 -p {config.conf.APPNAME} -c android.intent.category.LAUNCHER 1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@retry
|
|
||||||
def exit(self) -> None:
|
def exit(self) -> None:
|
||||||
"""exit the application"""
|
"""exit the application"""
|
||||||
logger.info("退出游戏")
|
logger.info("退出游戏")
|
||||||
self.run(f"am force-stop {config.conf.APPNAME}")
|
self.run(f"am force-stop {config.conf.APPNAME}")
|
||||||
|
|
||||||
@retry
|
|
||||||
def home(self) -> None:
|
def home(self) -> None:
|
||||||
"""back to home"""
|
"""back to home"""
|
||||||
logger.info("返回模拟器主页")
|
logger.info("返回模拟器主页")
|
||||||
|
@ -116,12 +117,12 @@ class Device:
|
||||||
)
|
)
|
||||||
|
|
||||||
@retry
|
@retry
|
||||||
|
@retry_adb
|
||||||
def send_keyevent(self, keycode: int) -> None:
|
def send_keyevent(self, keycode: int) -> None:
|
||||||
"""send a key event"""
|
"""send a key event"""
|
||||||
logger.debug(keycode)
|
logger.debug(keycode)
|
||||||
self.scrcpy.control.send_keyevent(keycode)
|
self.scrcpy.control.send_keyevent(keycode)
|
||||||
|
|
||||||
@retry
|
|
||||||
def send_text(self, text: str) -> None:
|
def send_text(self, text: str) -> None:
|
||||||
"""send a text"""
|
"""send a text"""
|
||||||
logger.debug(repr(text))
|
logger.debug(repr(text))
|
||||||
|
@ -139,6 +140,7 @@ class Device:
|
||||||
return bytes2img(data)
|
return bytes2img(data)
|
||||||
|
|
||||||
@retry
|
@retry
|
||||||
|
@retry_adb
|
||||||
def screencap(self) -> bytes:
|
def screencap(self) -> bytes:
|
||||||
start_time = datetime.now()
|
start_time = datetime.now()
|
||||||
min_time = config.screenshot_time + timedelta(
|
min_time = config.screenshot_time + timedelta(
|
||||||
|
@ -176,14 +178,12 @@ class Device:
|
||||||
save_screenshot(img)
|
save_screenshot(img)
|
||||||
return img
|
return img
|
||||||
|
|
||||||
@retry
|
|
||||||
def current_focus(self) -> str:
|
def current_focus(self) -> str:
|
||||||
"""detect current focus app"""
|
"""detect current focus app"""
|
||||||
command = "dumpsys window | grep mCurrentFocus"
|
command = "dumpsys window | grep mCurrentFocus"
|
||||||
line = self.run(command)
|
line = self.run(command)
|
||||||
return line.strip()[:-1].split(" ")[-1]
|
return line.strip()[:-1].split(" ")[-1]
|
||||||
|
|
||||||
@retry
|
|
||||||
def display_frames(self) -> tuple[int, int, int]:
|
def display_frames(self) -> tuple[int, int, int]:
|
||||||
"""get display frames if in compatibility mode"""
|
"""get display frames if in compatibility mode"""
|
||||||
if not config.MNT_COMPATIBILITY_MODE:
|
if not config.MNT_COMPATIBILITY_MODE:
|
||||||
|
@ -196,17 +196,20 @@ class Device:
|
||||||
return int(res[2]), int(res[4]), int(res[6])
|
return int(res[2]), int(res[4]), int(res[6])
|
||||||
|
|
||||||
@retry
|
@retry
|
||||||
|
@retry_adb
|
||||||
def tap(self, point: tuple[int, int]) -> None:
|
def tap(self, point: tuple[int, int]) -> None:
|
||||||
"""tap"""
|
"""tap"""
|
||||||
logger.debug(point)
|
logger.debug(point)
|
||||||
self.scrcpy.tap(point[0], point[1])
|
self.scrcpy.tap(point[0], point[1])
|
||||||
|
|
||||||
@retry
|
@retry
|
||||||
|
@retry_adb
|
||||||
def back(self):
|
def back(self):
|
||||||
logger.debug("back")
|
logger.debug("back")
|
||||||
self.scrcpy.back()
|
self.scrcpy.back()
|
||||||
|
|
||||||
@retry
|
@retry
|
||||||
|
@retry_adb
|
||||||
def swipe(
|
def swipe(
|
||||||
self, start: tuple[int, int], end: tuple[int, int], duration: int = 100
|
self, start: tuple[int, int], end: tuple[int, int], duration: int = 100
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -215,6 +218,7 @@ class Device:
|
||||||
self.scrcpy.swipe(start[0], start[1], end[0], end[1], duration / 1000)
|
self.scrcpy.swipe(start[0], start[1], end[0], end[1], duration / 1000)
|
||||||
|
|
||||||
@retry
|
@retry
|
||||||
|
@retry_adb
|
||||||
def swipe_ext(
|
def swipe_ext(
|
||||||
self,
|
self,
|
||||||
points: list[tp.Coordinate],
|
points: list[tp.Coordinate],
|
||||||
|
@ -238,7 +242,6 @@ class Device:
|
||||||
logger.debug(f"{points=} {durations=} {update=} {interval=} {func=}")
|
logger.debug(f"{points=} {durations=} {update=} {interval=} {func=}")
|
||||||
return self.scrcpy.swipe_ext(points, durations, update, interval, func)
|
return self.scrcpy.swipe_ext(points, durations, update, interval, func)
|
||||||
|
|
||||||
@retry
|
|
||||||
def check_current_focus(self) -> bool:
|
def check_current_focus(self) -> bool:
|
||||||
"""check if the application is in the foreground"""
|
"""check if the application is in the foreground"""
|
||||||
update = False
|
update = False
|
||||||
|
@ -264,7 +267,6 @@ class Device:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
update = True
|
update = True
|
||||||
|
|
||||||
@retry
|
|
||||||
def check_device_screen(self) -> bool:
|
def check_device_screen(self) -> bool:
|
||||||
"""检查分辨率和DPI
|
"""检查分辨率和DPI
|
||||||
|
|
||||||
|
|
|
@ -9,33 +9,26 @@ from adbutils import AdbClient, AdbDevice
|
||||||
from mower import __system__
|
from mower import __system__
|
||||||
from mower.utils import config
|
from mower.utils import config
|
||||||
from mower.utils.csleep import MowerExit
|
from mower.utils.csleep import MowerExit
|
||||||
from mower.utils.device.exception import SimulatorError
|
from mower.utils.device.exception import ADBError, SimulatorError
|
||||||
from mower.utils.device.utils import RETRY_TRIES, retry_sleep
|
|
||||||
from mower.utils.log import logger
|
from mower.utils.log import logger
|
||||||
|
|
||||||
from .utils import subprocess_run
|
from .utils import subprocess_run
|
||||||
|
|
||||||
|
|
||||||
def retry(func):
|
def retry_adb(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def retry_wrapper(self, *args, **kwargs):
|
def retry_wrapper(self, *args, **kwargs):
|
||||||
init = None
|
for attempt in range(2):
|
||||||
for _ in range(RETRY_TRIES):
|
|
||||||
try:
|
try:
|
||||||
if callable(init):
|
|
||||||
retry_sleep(_)
|
|
||||||
init()
|
|
||||||
return func(self, *args, **kwargs)
|
return func(self, *args, **kwargs)
|
||||||
except MowerExit:
|
except MowerExit:
|
||||||
break
|
raise
|
||||||
except Exception as e:
|
except ADBError as e:
|
||||||
|
logger.warning(f"ADB error, retrying... ({attempt + 1}/2)")
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
|
self.adb_reconnect()
|
||||||
def init():
|
# After adb retries fail, escalate to simulator error
|
||||||
self.adb_reconnect()
|
raise SimulatorError("ADB failed after 3 attempts.")
|
||||||
|
|
||||||
logger.error(f"Retry {func.__name__}() failed")
|
|
||||||
raise SimulatorError("无法连接ADB")
|
|
||||||
|
|
||||||
return retry_wrapper
|
return retry_wrapper
|
||||||
|
|
||||||
|
@ -46,21 +39,21 @@ class ADB:
|
||||||
self.check_server_status()
|
self.check_server_status()
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
@retry
|
@retry_adb
|
||||||
def adb(self) -> AdbDevice:
|
def adb(self) -> AdbDevice:
|
||||||
if len(self.adb_client.list()) == 0:
|
if len(self.adb_client.list()) == 0:
|
||||||
self.adb_client.connect(config.conf.adb, 3)
|
self.adb_client.connect(config.conf.adb, 5)
|
||||||
return AdbDevice(self.adb_client, config.conf.adb)
|
return AdbDevice(self.adb_client, config.conf.adb)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
@retry
|
@retry_adb
|
||||||
def adb_client(self) -> AdbClient:
|
def adb_client(self) -> AdbClient:
|
||||||
try:
|
try:
|
||||||
return AdbClient("127.0.0.1", config.adb_server_port, 5)
|
return AdbClient("127.0.0.1", config.adb_server_port, 5)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
@retry
|
@retry_adb
|
||||||
def adb_command(self, cmd, timeout=10):
|
def adb_command(self, cmd, timeout=10):
|
||||||
"""
|
"""
|
||||||
Execute ADB commands in a subprocess,
|
Execute ADB commands in a subprocess,
|
||||||
|
@ -83,27 +76,30 @@ class ADB:
|
||||||
logger.info(stdout)
|
logger.info(stdout)
|
||||||
return stdout
|
return stdout
|
||||||
|
|
||||||
|
def clear_cached_property(self, property_name: str):
|
||||||
|
if property_name in self.__dict__:
|
||||||
|
del self.__dict__[property_name]
|
||||||
|
|
||||||
def kill_server(self) -> None:
|
def kill_server(self) -> None:
|
||||||
self.adb_command(["kill-server"])
|
self.adb_command(["kill-server"])
|
||||||
del self.__dict__["adb_client"]
|
self.clear_cached_property("adb_client")
|
||||||
del self.__dict__["adb"]
|
self.clear_cached_property("adb")
|
||||||
|
|
||||||
def restart_server(self) -> None:
|
def restart_server(self) -> None:
|
||||||
self.kill_server()
|
self.kill_server()
|
||||||
self.check_server_status()
|
self.check_server_status()
|
||||||
|
|
||||||
def adb_disconnect(self):
|
def adb_disconnect(self):
|
||||||
self.adb_client.disconnect(config.conf.adb)
|
self.adb_client.disconnect(config.conf.adb, raise_error=False)
|
||||||
del self.__dict__["adb"]
|
self.clear_cached_property("adb")
|
||||||
|
|
||||||
def adb_reconnect(self):
|
def adb_reconnect(self):
|
||||||
status = self.check_server_status()
|
status = self.check_server_status()
|
||||||
if "offline" in status:
|
if "offline" in status:
|
||||||
self.adb_disconnect()
|
self.adb_disconnect()
|
||||||
elif config.conf.adb in status:
|
else:
|
||||||
self.restart_server()
|
self.restart_server()
|
||||||
|
|
||||||
@retry
|
|
||||||
def adb_shell(
|
def adb_shell(
|
||||||
self, cmd, stream=False, timeout=10, encoding: str | None = "utf-8", rstrip=True
|
self, cmd, stream=False, timeout=10, encoding: str | None = "utf-8", rstrip=True
|
||||||
):
|
):
|
||||||
|
|
|
@ -9,7 +9,6 @@ from mower.utils import config
|
||||||
from mower.utils.csleep import MowerExit
|
from mower.utils.csleep import MowerExit
|
||||||
from mower.utils.device.exception import ADBError
|
from mower.utils.device.exception import ADBError
|
||||||
from mower.utils.device.method.adb import ADB
|
from mower.utils.device.method.adb import ADB
|
||||||
from mower.utils.device.utils import retry_sleep
|
|
||||||
from mower.utils.image import bytes2img
|
from mower.utils.image import bytes2img
|
||||||
from mower.utils.log import logger
|
from mower.utils.log import logger
|
||||||
from mower.utils.network import get_new_port, is_port_in_use
|
from mower.utils.network import get_new_port, is_port_in_use
|
||||||
|
@ -19,27 +18,20 @@ class DroidCastError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def retry(func):
|
def retry_droidcast(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def retry_wrapper(self, *args, **kwargs):
|
def retry_wrapper(self, *args, **kwargs):
|
||||||
init = None
|
for try_count in range(2):
|
||||||
exception = ""
|
|
||||||
for _ in range(3):
|
|
||||||
try:
|
try:
|
||||||
if callable(init):
|
|
||||||
retry_sleep(_)
|
|
||||||
init()
|
|
||||||
return func(self, *args, **kwargs)
|
return func(self, *args, **kwargs)
|
||||||
except MowerExit:
|
except MowerExit:
|
||||||
break
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
exception = e
|
logger.exception(e)
|
||||||
|
self.start_droidcast()
|
||||||
def init():
|
try_count += 1
|
||||||
self.start_droidcast()
|
# After scrcpy retries fail, escalate to adb error
|
||||||
|
raise ADBError("Droidcast failed after 2 attempts.")
|
||||||
logger.error(f"Retry {func.__name__}() failed")
|
|
||||||
raise ADBError(exception)
|
|
||||||
|
|
||||||
return retry_wrapper
|
return retry_wrapper
|
||||||
|
|
||||||
|
@ -119,7 +111,7 @@ class DroidCast:
|
||||||
time.sleep(1) # TODO: 更好地等待DroidCast启动
|
time.sleep(1) # TODO: 更好地等待DroidCast启动
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@retry
|
@retry_droidcast
|
||||||
def capture_display(self):
|
def capture_display(self):
|
||||||
try:
|
try:
|
||||||
url = f"http://127.0.0.1:{self.port}/screenshot"
|
url = f"http://127.0.0.1:{self.port}/screenshot"
|
||||||
|
|
|
@ -4,6 +4,7 @@ import functools
|
||||||
import socket
|
import socket
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
from functools import wraps
|
||||||
from typing import Any, Callable, Optional
|
from typing import Any, Callable, Optional
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
@ -11,7 +12,8 @@ from adbutils import AdbConnection, Network
|
||||||
|
|
||||||
from mower.utils import config
|
from mower.utils import config
|
||||||
from mower.utils import typealias as tp
|
from mower.utils import typealias as tp
|
||||||
from mower.utils.device.exception import ADBError
|
from mower.utils.csleep import MowerExit
|
||||||
|
from mower.utils.device.exception import ADBError, SimulatorError
|
||||||
from mower.utils.device.method.adb import ADB
|
from mower.utils.device.method.adb import ADB
|
||||||
from mower.utils.device.method.adb.const import KeyCode
|
from mower.utils.device.method.adb.const import KeyCode
|
||||||
from mower.utils.log import logger
|
from mower.utils.log import logger
|
||||||
|
@ -35,6 +37,30 @@ def recog_start(func: Callable[[tp.Image], Any] = lambda _: None):
|
||||||
swipe_update_result = func(config.recog.img)
|
swipe_update_result = func(config.recog.img)
|
||||||
|
|
||||||
|
|
||||||
|
def retry_scrcpy(func):
|
||||||
|
@wraps(func)
|
||||||
|
def retry_wrapper(self, *args, **kwargs):
|
||||||
|
for try_count in range(2):
|
||||||
|
try:
|
||||||
|
return func(self, *args, **kwargs)
|
||||||
|
except MowerExit:
|
||||||
|
raise
|
||||||
|
except (
|
||||||
|
ConnectionResetError,
|
||||||
|
BrokenPipeError,
|
||||||
|
ConnectionAbortedError,
|
||||||
|
) as e:
|
||||||
|
logger.exception(e)
|
||||||
|
self.stop()
|
||||||
|
time.sleep(1)
|
||||||
|
self.start()
|
||||||
|
try_count += 1
|
||||||
|
# After scrcpy retries fail, escalate to adb error
|
||||||
|
raise ADBError("Scrcpy failed after 2 attempts.")
|
||||||
|
|
||||||
|
return retry_wrapper
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -184,20 +210,22 @@ class Client:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
self.start()
|
self.start()
|
||||||
try_count += 1
|
try_count += 1
|
||||||
|
except SimulatorError as e:
|
||||||
|
logger.exception(e)
|
||||||
else:
|
else:
|
||||||
raise ADBError("Failed to start scrcpy-server.")
|
raise ADBError("Failed to start scrcpy-server.")
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
@stable
|
@retry_scrcpy
|
||||||
def tap(self, x: int, y: int) -> None:
|
def tap(self, x: int, y: int) -> None:
|
||||||
self.control.tap(x, y)
|
self.control.tap(x, y)
|
||||||
|
|
||||||
@stable
|
@retry_scrcpy
|
||||||
def back(self):
|
def back(self):
|
||||||
self.control.send_keyevent(KeyCode.KEYCODE_BACK)
|
self.control.send_keyevent(KeyCode.KEYCODE_BACK)
|
||||||
|
|
||||||
@stable
|
@retry_scrcpy
|
||||||
def swipe(
|
def swipe(
|
||||||
self,
|
self,
|
||||||
x0: int,
|
x0: int,
|
||||||
|
@ -258,7 +286,7 @@ class Client:
|
||||||
if interval > 0:
|
if interval > 0:
|
||||||
time.sleep(interval)
|
time.sleep(interval)
|
||||||
|
|
||||||
@stable
|
@retry_scrcpy
|
||||||
def swipe_ext(
|
def swipe_ext(
|
||||||
self,
|
self,
|
||||||
points: list[tp.Coordinate],
|
points: list[tp.Coordinate],
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
from datetime import datetime
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from os import system
|
from os import system
|
||||||
|
|
||||||
|
@ -131,13 +130,6 @@ def exec_cmd(cmd, folder_path, wait_time):
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
wait_time -= 1
|
wait_time -= 1
|
||||||
else:
|
else:
|
||||||
start_time = datetime.now()
|
csleep(wait_time)
|
||||||
while (datetime.now() - start_time).total_seconds() < wait_time:
|
return True
|
||||||
try:
|
|
||||||
config.device.check_device_screen()
|
|
||||||
except MowerExit:
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
logger.debug_exception(e)
|
|
||||||
csleep(1)
|
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
import time
|
|
||||||
|
|
||||||
RETRY_TRIES = 5
|
|
||||||
RETRY_DELAY = 3
|
|
||||||
|
|
||||||
|
|
||||||
def retry_sleep(trial):
|
|
||||||
# First trial
|
|
||||||
if trial == 0:
|
|
||||||
pass
|
|
||||||
# Failed once, fast retry
|
|
||||||
elif trial == 1:
|
|
||||||
pass
|
|
||||||
# Failed twice
|
|
||||||
elif trial == 2:
|
|
||||||
time.sleep(1)
|
|
||||||
# Failed more
|
|
||||||
else:
|
|
||||||
time.sleep(RETRY_DELAY)
|
|
Loading…
Add table
Add a link
Reference in a new issue