diff --git a/IMPLEMENTATION_SUMMARY.md b/IMPLEMENTATION_SUMMARY.md index 70f9b469..7a1d3c41 100644 --- a/IMPLEMENTATION_SUMMARY.md +++ b/IMPLEMENTATION_SUMMARY.md @@ -42,12 +42,12 @@ #### 同步版本 - `get_region(region=None)`: 获取缓存区域名称 -- `get_cache_key(func, args, kwargs)`: 根据函数和参数生成缓存键 +- `get_cache_key(func, args, kwargs)`: 根据函数和参数生成缓存键(使用inspect.signature,支持默认值和self/cls参数处理) - `is_redis()`: 判断当前缓存后端是否为Redis #### 异步版本 - `get_region(region=None)`: 获取缓存区域名称 -- `get_cache_key(func, args, kwargs)`: 根据函数和参数生成缓存键 +- `get_cache_key(func, args, kwargs)`: 根据函数和参数生成缓存键(使用inspect.signature,支持默认值和self/cls参数处理) - `is_redis()`: 判断当前缓存后端是否为Redis ### 3. 代码优化 @@ -55,6 +55,7 @@ - 删除了重复的方法定义 - 统一了CacheBackend和AsyncCacheBackend的接口 - 简化了TTLCache类,去掉了dict-like方法,只保留基本功能 +- 修复了get_cache_key方法,使其与旧实现保持一致,满足装饰器需要 - 保持了向后兼容性 ## 使用示例 @@ -199,7 +200,7 @@ cache = AsyncCache(maxsize=1024, ttl=600) ### 辅助方法 ✅ `get_region()` 方法完整 -✅ `get_cache_key()` 方法完整 +✅ `get_cache_key()` 方法完整(修复后与旧实现保持一致,支持装饰器) ✅ `is_redis()` 方法完整 ✅ CacheBackend和AsyncCacheBackend方法数量一致(16个方法) diff --git a/app/core/cache.py b/app/core/cache.py index b51a3c8e..9767a34b 100644 --- a/app/core/cache.py +++ b/app/core/cache.py @@ -217,19 +217,20 @@ class CacheBackend(ABC): :param kwargs: 关键字参数 :return: 缓存键 """ - # 使用函数名和参数生成缓存键 - key_parts = [func.__module__, func.__name__] - - # 添加位置参数 - if args: - key_parts.extend([str(arg) for arg in args]) - - # 添加关键字参数(排序以确保一致性) - if kwargs: - sorted_kwargs = sorted(kwargs.items()) - key_parts.extend([f"{k}={v}" for k, v in sorted_kwargs]) - - return hashkey(*key_parts) + signature = inspect.signature(func) + # 绑定传入的参数并应用默认值 + bound = signature.bind(*args, **kwargs) + bound.apply_defaults() + # 忽略第一个参数,如果它是实例(self)或类(cls) + parameters = list(signature.parameters.keys()) + if parameters and parameters[0] in ("self", "cls"): + bound.arguments.pop(parameters[0], None) + # 按照函数签名顺序提取参数值列表 + keys = [ + bound.arguments[param] for param in signature.parameters if param in bound.arguments + ] + # 使用有序参数生成缓存键 + return f"{func.__name__}_{hashkey(*keys)}" def is_redis(self) -> bool: """ @@ -437,19 +438,20 @@ class AsyncCacheBackend(ABC): :param kwargs: 关键字参数 :return: 缓存键 """ - # 使用函数名和参数生成缓存键 - key_parts = [func.__module__, func.__name__] - - # 添加位置参数 - if args: - key_parts.extend([str(arg) for arg in args]) - - # 添加关键字参数(排序以确保一致性) - if kwargs: - sorted_kwargs = sorted(kwargs.items()) - key_parts.extend([f"{k}={v}" for k, v in sorted_kwargs]) - - return hashkey(*key_parts) + signature = inspect.signature(func) + # 绑定传入的参数并应用默认值 + bound = signature.bind(*args, **kwargs) + bound.apply_defaults() + # 忽略第一个参数,如果它是实例(self)或类(cls) + parameters = list(signature.parameters.keys()) + if parameters and parameters[0] in ("self", "cls"): + bound.arguments.pop(parameters[0], None) + # 按照函数签名顺序提取参数值列表 + keys = [ + bound.arguments[param] for param in signature.parameters if param in bound.arguments + ] + # 使用有序参数生成缓存键 + return f"{func.__name__}_{hashkey(*keys)}" def is_redis(self) -> bool: """