Async backoff

``asyncbackoff `` декоратор который обеспечивает политику повторов и политику максимального количества повторных попыток выполнения асинхронной функции.

Основной принцип может быть описан пятью правилами:

  • функция будет отменена, если она будет выполнена дольше, чем deadline (если указано)

  • функция будет отменена при выполнении дольше, чем ``attempt_timeout` (если указано) после этого будет выполнена повторная попытка.

  • Попытки выполняются после pause секунд (если указано, по умолчанию 0)

  • Попытки будут выполняться не более max_tries раз.

  • аргумент giveup - это функция, которая решает, следует ли «сдаться» и прекратить дальнейшие попыток или продолжать.

Все эти правила работают одновременно.

Описание аргументов:

  • attempt_timeout максимально допустимое время выполнения одной попытки.

  • deadline максимально допустимое время выполнения всех попыток.

  • pause промежуток времени между попытками.

  • exceptions делает последующие попытки только если эти будут брошены эти исключения.

  • giveup (именовынный аргумент) это функция-предикат, которая может решить по данному исключению, следует ли нам продолжать повторять попытки.

  • max_tries (именовынный аргумент) - максимальное количество попыток (> = 1).

Декоратор, обеспечивающий соблюдение временных ограничений «attempt_timeout» и «deadline» декорированной функцией.

В случае возникновения исключения функция будет вызвана снова с аналогичными аргументами через кол-во секунд переданное в аргументе «pause».

Объявление через позиционные аргументы:

from aiomisc import asyncbackoff

attempt_timeout = 0.1
deadline = 1
pause = 0.1

@asyncbackoff(attempt_timeout, deadline, pause)
async def db_fetch():
    ...


@asyncbackoff(0.1, 1, 0.1)
async def db_save(data: dict):
    ...


# Passing exceptions for handling
@asyncbackoff(0.1, 1, 0.1, TypeError, RuntimeError, ValueError)
async def db_fetch(data: dict):
    ...

Объявление через именованные аргументы

from aiomisc import asyncbackoff

attempt_timeout = 0.1
deadline = 1
pause = 0.1

@asyncbackoff(attempt_timeout=attempt_timeout,
              deadline=deadline, pause=pause)
async def db_fetch():
    ...


@asyncbackoff(attempt_timeout=0.1, deadline=1, pause=0.1)
async def db_save(data: dict):
    ...


# Passing exceptions for handling
@asyncbackoff(attempt_timeout=0.1, deadline=1, pause=0.1,
              exceptions=[TypeError, RuntimeError, ValueError])
async def db_fetch(data: dict):
    ...


# Will be retried no more than 2 times (3 tries total)
@asyncbackoff(attempt_timeout=0.5, deadline=1, pause=0.1, max_tries=3,
              exceptions=[TypeError, RuntimeError, ValueError])
async def db_fetch(data: dict):
    ...


# Will be retried only on connection abort (on POSIX systems)
@asyncbackoff(attempt_timeout=0.5, deadline=1, pause=0.1,
              exceptions=[OSError],
              giveup=lambda e: e.errno != errno.ECONNABORTED)
async def db_fetch(data: dict):
    ...

asyncretry

Аналог asyncbackoff(None, None, 0, *args, **kwargs). Прсто повторяет выполнение функции max_tries раз.

Примечание

По умолчанию будет повторена попытка при любом исключении. Это очень просто и полезно в общих случаях, при этом следует указать список исключений тогда, когда обернутые функции вызывают сотни раз в секунду, потому что у вас есть риск быть причиной отказа в обслуживании в случае, если ваша функция вызывает какой-то сервис по сети.

from aiomisc import asyncretry

@asyncretry(5)
async def try_download_file(url):
    ...

@asyncretry(3, exceptions=(ConnectionError,))
async def get_cluster_lock():
    ...