2024-07-24 10:44:06 +00:00
|
|
|
import random
|
2024-09-27 10:19:39 +00:00
|
|
|
import time
|
|
|
|
from typing import List, Type
|
2024-07-24 10:44:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
def retry(
|
2024-09-30 20:42:47 +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-09-30 20:42:47 +00:00
|
|
|
exceptions = exceptions or (Exception,)
|
|
|
|
|
2024-09-30 20:13:56 +00:00
|
|
|
def inner(func, *args, **kwargs):
|
|
|
|
current_delay = delay
|
|
|
|
for retry in range(retries):
|
|
|
|
try:
|
|
|
|
func(*args, **kwargs)
|
|
|
|
break
|
|
|
|
except Exception as e:
|
2024-09-30 20:42:47 +00:00
|
|
|
should_retry = (retry < retries - 1) and any(
|
|
|
|
isinstance(e, re) for re in exceptions
|
2024-09-30 20:13:56 +00:00
|
|
|
)
|
|
|
|
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
|