grouphyx/utils/retry.py

56 lines
1.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""简单的重试工具:指数退避 + 抖动。
课程设计场景不引入额外依赖(如 tenacity保持轻量。
"""
from __future__ import annotations
import random
import time
from typing import Callable, TypeVar, Tuple
T = TypeVar("T")
def retry(
*,
max_retries: int = 3,
initial_delay: float = 1.0,
backoff_factor: float = 2.0,
max_delay: float = 10.0,
jitter: float = 0.2,
retry_exceptions: Tuple[type[BaseException], ...] = (Exception,),
):
"""重试装饰器。
- 第一次失败后等待 initial_delay
- 之后按照 backoff_factor 指数增长
- 加一点 jitter 防止固定间隔
"""
def decorator(func: Callable[..., T]) -> Callable[..., T]:
def wrapper(*args, **kwargs) -> T:
delay = initial_delay
last_exc: BaseException | None = None
for attempt in range(max_retries + 1):
try:
return func(*args, **kwargs)
except retry_exceptions as exc: # noqa: PERF203
last_exc = exc
if attempt >= max_retries:
raise
# jitterdelay*(1±jitter)
factor = 1.0 + random.uniform(-jitter, jitter)
sleep_s = min(max_delay, max(0.0, delay * factor))
time.sleep(sleep_s)
delay = min(max_delay, delay * backoff_factor)
# 理论上不会走到这里
assert last_exc is not None
raise last_exc
return wrapper
return decorator