def async_exponential_backoff()

in neuron_explainer/api_client.py [0:0]


def async_exponential_backoff(retry_on=lambda err: True):
    """
    Returns a decorator which retries the wrapped function as long as the specified retry_on
    function returns True for the exception, applying exponential backoff with jitter after
    failures, up to a retry limit.
    """
    init_delay_s = 1
    max_delay_s = 10
    backoff_multiplier = 2.0
    jitter = 0.2

    def decorate(f):
        @wraps(f)
        async def f_retry(self, *args, **kwargs):
            max_tries = 200
            delay_s = init_delay_s
            for i in range(max_tries):
                try:
                    return await f(self, *args, **kwargs)
                except Exception as err:
                    if i == max_tries - 1:
                        print(f"Exceeded max tries ({max_tries}) on HTTP request")
                        raise
                    if not retry_on(err):
                        print("Unretryable error on HTTP request")
                        raise
                    jittered_delay = random.uniform(delay_s * (1 - jitter), delay_s * (1 + jitter))
                    await asyncio.sleep(jittered_delay)
                    delay_s = min(delay_s * backoff_multiplier, max_delay_s)

        return f_retry

    return decorate