Skip to content

Commit d70fd85

Browse files
committed
refactor: remove tenacity
Use custom retry logic
1 parent d8cd5bf commit d70fd85

File tree

1 file changed

+43
-7
lines changed

1 file changed

+43
-7
lines changed

src/mega/api.py

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
import asyncio
44
import contextlib
55
import logging
6-
from typing import TYPE_CHECKING, Any, ClassVar, Self
6+
from collections.abc import Sequence
7+
from functools import wraps
8+
from typing import TYPE_CHECKING, Any, ClassVar, ParamSpec, Self, TypeVar
79

810
import aiohttp
9-
import tenacity
1011
import yarl
1112

1213
from mega.crypto import generate_hashcash_token
@@ -15,7 +16,10 @@
1516
from .errors import RequestError, RetryRequestError
1617

1718
if TYPE_CHECKING:
18-
from collections.abc import AsyncGenerator
19+
from collections.abc import AsyncGenerator, Callable, Coroutine
20+
21+
_P = ParamSpec("_P")
22+
_R = TypeVar("_R")
1923

2024

2125
logger = logging.getLogger(__name__)
@@ -27,6 +31,41 @@
2731
}
2832

2933

34+
def retry(
35+
*,
36+
exceptions: Sequence[type[Exception]] | type[Exception],
37+
attempts: int = 10,
38+
delay: float = 0.5,
39+
min_delay: float = 2.0,
40+
max_delay: float = 30.0,
41+
backoff: int = 2,
42+
) -> Callable[[Callable[_P, _R]], Callable[_P, Coroutine[None, None, _R]]]:
43+
if not isinstance(exceptions, Sequence):
44+
exceptions = [exceptions]
45+
46+
def wrapper(func: Callable[_P, _R]) -> Callable[_P, Coroutine[None, None, _R]]:
47+
@wraps(func)
48+
async def inner_wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _R:
49+
current_delay = delay
50+
for attempt in range(1, attempts + 1):
51+
try:
52+
return func(*args, **kwargs)
53+
except tuple(exceptions) as exc:
54+
if attempt >= attempts:
55+
raise
56+
57+
logger.warning(f"Retrying {func.__qualname__} after attempt {attempt} ({exc})")
58+
await asyncio.sleep(current_delay)
59+
exp = current_delay**backoff
60+
current_delay = max(min_delay, min(exp, max_delay))
61+
else:
62+
raise RuntimeError
63+
64+
return inner_wrapper
65+
66+
return wrapper
67+
68+
3069
class MegaAPI:
3170
__slots__ = (
3271
"__session",
@@ -63,10 +102,7 @@ def _lazy_session(self) -> aiohttp.ClientSession:
63102
self.__session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(sock_connect=160, sock_read=60))
64103
return self.__session
65104

66-
@tenacity.retry(
67-
retry=tenacity.retry_if_exception_type(RetryRequestError),
68-
wait=tenacity.wait_exponential(multiplier=2, min=2, max=60),
69-
)
105+
@retry(exceptions=RetryRequestError, attempts=10, max_delay=60.0)
70106
async def request(self, data: dict[str, Any] | list[dict[str, Any]], params: dict[str, Any] | None = None) -> Any:
71107
params = {"id": self._request_id} | (params or {})
72108
self._request_id += 1

0 commit comments

Comments
 (0)