first commit
This commit is contained in:
88
wechat_auto/utils/retry.py
Normal file
88
wechat_auto/utils/retry.py
Normal file
@@ -0,0 +1,88 @@
|
||||
import asyncio
|
||||
import functools
|
||||
from typing import Callable, Any, TypeVar, Coroutine
|
||||
from wechat_auto.utils.logger import logger
|
||||
from wechat_auto.config import settings
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
def async_retry(
|
||||
max_retries: int = None,
|
||||
base_delay: float = None,
|
||||
exponential: bool = True,
|
||||
exceptions: tuple = (Exception,)
|
||||
):
|
||||
max_retries = max_retries or settings.max_retries
|
||||
base_delay = base_delay or settings.retry_base_delay
|
||||
|
||||
def decorator(func: Callable[..., Coroutine[Any, Any, T]]):
|
||||
@functools.wraps(func)
|
||||
async def wrapper(*args, **kwargs) -> T:
|
||||
last_exception = None
|
||||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
return await func(*args, **kwargs)
|
||||
except exceptions as e:
|
||||
last_exception = e
|
||||
if attempt < max_retries - 1:
|
||||
if exponential:
|
||||
delay = base_delay * (2 ** attempt)
|
||||
else:
|
||||
delay = base_delay
|
||||
logger.warning(
|
||||
f"{func.__name__} 失败,{attempt + 1}/{max_retries},"
|
||||
f"{delay:.1f}秒后重试: {e}"
|
||||
)
|
||||
await asyncio.sleep(delay)
|
||||
else:
|
||||
logger.error(
|
||||
f"{func.__name__} 失败,已达到最大重试次数 {max_retries}: {e}"
|
||||
)
|
||||
|
||||
raise last_exception
|
||||
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
def sync_retry(
|
||||
max_retries: int = None,
|
||||
base_delay: float = None,
|
||||
exponential: bool = True,
|
||||
exceptions: tuple = (Exception,)
|
||||
):
|
||||
max_retries = max_retries or settings.max_retries
|
||||
base_delay = base_delay or settings.retry_base_delay
|
||||
|
||||
def decorator(func: Callable[..., T]):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs) -> T:
|
||||
last_exception = None
|
||||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except exceptions as e:
|
||||
last_exception = e
|
||||
if attempt < max_retries - 1:
|
||||
if exponential:
|
||||
delay = base_delay * (2 ** attempt)
|
||||
else:
|
||||
delay = base_delay
|
||||
logger.warning(
|
||||
f"{func.__name__} 失败,{attempt + 1}/{max_retries},"
|
||||
f"{delay:.1f}秒后重试: {e}"
|
||||
)
|
||||
import time
|
||||
time.sleep(delay)
|
||||
else:
|
||||
logger.error(
|
||||
f"{func.__name__} 失败,已达到最大重试次数 {max_retries}: {e}"
|
||||
)
|
||||
|
||||
raise last_exception
|
||||
|
||||
return wrapper
|
||||
return decorator
|
||||
Reference in New Issue
Block a user