first commit
This commit is contained in:
0
utils/__init__.py
Normal file
0
utils/__init__.py
Normal file
BIN
utils/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
utils/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
utils/__pycache__/logger.cpython-313.pyc
Normal file
BIN
utils/__pycache__/logger.cpython-313.pyc
Normal file
Binary file not shown.
BIN
utils/__pycache__/retry.cpython-313.pyc
Normal file
BIN
utils/__pycache__/retry.cpython-313.pyc
Normal file
Binary file not shown.
34
utils/logger.py
Normal file
34
utils/logger.py
Normal file
@@ -0,0 +1,34 @@
|
||||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from wechat_auto.config import settings
|
||||
|
||||
|
||||
def setup_logger(name: str = "wechat_auto") -> logging.Logger:
|
||||
logger = logging.getLogger(name)
|
||||
|
||||
if logger.handlers:
|
||||
return logger
|
||||
|
||||
logger.setLevel(getattr(logging, settings.log_level.upper()))
|
||||
|
||||
formatter = logging.Formatter(
|
||||
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
console_handler.setFormatter(formatter)
|
||||
logger.addHandler(console_handler)
|
||||
|
||||
try:
|
||||
file_handler = logging.FileHandler(settings.log_file)
|
||||
file_handler.setFormatter(formatter)
|
||||
logger.addHandler(file_handler)
|
||||
except Exception as e:
|
||||
logger.warning(f"无法创建日志文件: {e}")
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
logger = setup_logger()
|
||||
88
utils/retry.py
Normal file
88
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