mirror of
https://github.com/fawney19/Aether.git
synced 2026-01-11 12:08:30 +08:00
76 lines
2.6 KiB
Python
76 lines
2.6 KiB
Python
"""缓存装饰器工具"""
|
||
|
||
import functools
|
||
import json
|
||
from typing import Any, Callable, Optional
|
||
|
||
from src.core.logger import logger
|
||
|
||
from src.clients.redis_client import get_redis_client_sync
|
||
|
||
|
||
def cache_result(key_prefix: str, ttl: int = 60, user_specific: bool = True) -> Callable:
|
||
"""
|
||
缓存函数结果的装饰器
|
||
|
||
Args:
|
||
key_prefix: 缓存键前缀
|
||
ttl: 缓存过期时间(秒)
|
||
user_specific: 是否针对用户缓存(从 context.user.id 获取)
|
||
"""
|
||
|
||
def decorator(func: Callable) -> Callable:
|
||
@functools.wraps(func)
|
||
async def wrapper(*args, **kwargs) -> Any:
|
||
redis_client = get_redis_client_sync()
|
||
|
||
# 如果 Redis 不可用,直接执行原函数
|
||
if redis_client is None:
|
||
return await func(*args, **kwargs)
|
||
|
||
# 构建缓存键
|
||
try:
|
||
# 从 args 中获取 context(通常是第一个参数)
|
||
context = args[0] if args else None
|
||
|
||
if user_specific and context and hasattr(context, "user") and context.user:
|
||
cache_key = f"{key_prefix}:user:{context.user.id}"
|
||
else:
|
||
cache_key = f"{key_prefix}:global"
|
||
|
||
# 如果有额外的参数(如 days),添加到键中
|
||
if hasattr(args[0], "__dict__"):
|
||
# 如果是 dataclass 或对象,获取其属性
|
||
for attr_name in ["days", "limit"]:
|
||
if hasattr(args[0], attr_name):
|
||
attr_value = getattr(args[0], attr_name)
|
||
cache_key += f":{attr_name}:{attr_value}"
|
||
|
||
# 尝试从缓存获取
|
||
cached = await redis_client.get(cache_key)
|
||
if cached:
|
||
logger.debug(f"缓存命中: {cache_key}")
|
||
return json.loads(cached)
|
||
|
||
# 执行原函数
|
||
result = await func(*args, **kwargs)
|
||
|
||
# 保存到缓存
|
||
try:
|
||
await redis_client.setex(
|
||
cache_key, ttl, json.dumps(result, ensure_ascii=False, default=str)
|
||
)
|
||
logger.debug(f"缓存已保存: {cache_key}, TTL: {ttl}s")
|
||
except Exception as e:
|
||
logger.warning(f"保存缓存失败: {e}")
|
||
|
||
return result
|
||
|
||
except Exception as e:
|
||
logger.warning(f"缓存处理出错: {e}, 直接执行原函数")
|
||
return await func(*args, **kwargs)
|
||
|
||
return wrapper
|
||
|
||
return decorator
|