Исходный код raito.utils.helpers.retry_method

from __future__ import annotations

import asyncio
import inspect
import warnings
from collections.abc import Awaitable, Callable
from typing import ParamSpec, TypeVar

from aiogram.exceptions import (
    TelegramNetworkError,
    TelegramRetryAfter,
    TelegramServerError,
)

P = ParamSpec("P")
T = TypeVar("T")

MAX_ATTEMPTS: int = 5
ADDITIONAL_DELAY: float = 0.1
MAX_DELAY: float = 30.0


[документация] async def retry_method( func: Callable[P, Awaitable[T]], *args: P.args, **kwargs: P.kwargs, ) -> T: """Call an async function and retry it on Telegram errors. Pass the coroutine function together with its arguments. Example: .. code-block:: python await rt.retry(bot.send_message, chat_id, "text") await rt.retry(message.answer, "text") Retries on ``TelegramRetryAfter`` (honouring the server-provided ``retry_after``) and on network/server errors (``TelegramNetworkError``, ``TelegramServerError``) using exponential delay. Any other exception is raised immediately. :param func: A coroutine function to call on each attempt. :param args: Positional arguments forwarded to ``func``. :param kwargs: Keyword arguments forwarded to ``func``. :return: Result of the func. :raises Exception: If all attempts fail or a non-RetryAfter exception is raised. .. deprecated:: 1.6.0 Passing an already-created coroutine (``rt.retry(bot.send_message(...))``) is deprecated and will stop working in 1.8.0. It is awaited only once and cannot be retried. Pass the function and its arguments instead: ``rt.retry(bot.send_message, chat_id, text)``. """ if inspect.isawaitable(func): warnings.warn( "Passing an already-created coroutine to rt.retry is deprecated " "since 1.6.0 and will stop working in 1.8.0: a coroutine can only be " "awaited once, so it cannot be retried. Call it as " "rt.retry(func, *args, **kwargs). " "e.g. rt.retry(bot.send_message, chat_id, text) instead of " "rt.retry(bot.send_message(chat_id, text)).", DeprecationWarning, stacklevel=2, ) return await func attempt: int = 0 while True: attempt += 1 try: return await func(*args, **kwargs) except TelegramRetryAfter as exc: if attempt >= MAX_ATTEMPTS: raise await asyncio.sleep(exc.retry_after + ADDITIONAL_DELAY) except (TelegramNetworkError, TelegramServerError): if attempt >= MAX_ATTEMPTS: raise await asyncio.sleep(min(ADDITIONAL_DELAY * 2 ** (attempt - 1), MAX_DELAY))