2024-07-24 10:44:06 +00:00
|
|
|
import time
|
|
|
|
import random
|
|
|
|
from typing import Type, List
|
|
|
|
|
|
|
|
|
|
|
|
def retry(
|
2024-10-02 17:08:59 +00:00
|
|
|
*exceptions: Type[BaseException],
|
2024-07-24 10:44:06 +00:00
|
|
|
retries: int = 5,
|
|
|
|
delay: float = 1,
|
|
|
|
backoff: float = 1.5,
|
|
|
|
jitter: float = 2,
|
2024-07-31 12:00:09 +00:00
|
|
|
log_function=None, # should take **kwargs or arguments: `retry_number`, `exception` and `sleep_time`
|
2024-07-24 10:44:06 +00:00
|
|
|
):
|
2024-10-02 17:08:59 +00:00
|
|
|
exceptions = exceptions or (Exception,)
|
2024-07-24 10:44:06 +00:00
|
|
|
|
2024-10-02 17:08:59 +00:00
|
|
|
def inner(func, *args, **kwargs):
|
|
|
|
current_delay = delay
|
|
|
|
for retry in range(retries):
|
|
|
|
try:
|
|
|
|
func(*args, **kwargs)
|
|
|
|
break
|
|
|
|
except Exception as e:
|
|
|
|
should_retry = (retry < retries - 1) and any(
|
|
|
|
isinstance(e, re) for re in exceptions
|
|
|
|
)
|
|
|
|
if not should_retry:
|
|
|
|
raise e
|
|
|
|
sleep_time = current_delay + random.uniform(0, jitter)
|
|
|
|
if log_function is not None:
|
|
|
|
log_function(retry_number=retry, exception=e, sleep_time=sleep_time)
|
|
|
|
time.sleep(sleep_time)
|
|
|
|
current_delay *= backoff
|
2024-07-24 10:44:06 +00:00
|
|
|
|
|
|
|
return inner
|