diff --git a/app/core/cache.py b/app/core/cache.py index 881250d9..a198af46 100644 --- a/app/core/cache.py +++ b/app/core/cache.py @@ -205,31 +205,6 @@ class CacheBackend(ABC): """ return f"region:{region}" if region else "region:default" - @staticmethod - def get_cache_key(func, args, kwargs) -> str: - """ - 根据函数和参数生成缓存键 - - :param func: 函数对象 - :param args: 位置参数 - :param kwargs: 关键字参数 - :return: 缓存键 - """ - 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)}" - @staticmethod def is_redis() -> bool: """ @@ -764,7 +739,7 @@ class FileBackend(CacheBackend): for item in cache_path.iterdir(): if item.is_file(): with open(item, 'r') as f: - yield item.name, f.read() + yield item.as_posix(), f.read() def close(self) -> None: """ @@ -877,7 +852,7 @@ class AsyncFileBackend(AsyncCacheBackend): async for item in cache_path.iterdir(): if await item.is_file(): async with aiofiles.open(item, 'r') as f: - yield item.name, await f.read() + yield item.as_posix(), await f.read() async def close(self) -> None: """ @@ -971,6 +946,29 @@ def cached(region: Optional[str] = None, maxsize: Optional[int] = 1024, ttl: Opt def decorator(func): + def __get_cache_key(args, kwargs) -> str: + """ + 根据函数和参数生成缓存键 + + :param args: 位置参数 + :param kwargs: 关键字参数 + :return: 缓存键 + """ + 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)}" + # 获取缓存区 cache_region = region if region is not None else f"{func.__module__}.{func.__name__}" @@ -982,7 +980,7 @@ def cached(region: Optional[str] = None, maxsize: Optional[int] = 1024, ttl: Opt @wraps(func) async def async_wrapper(*args, **kwargs): # 获取缓存键 - cache_key = cache_backend.get_cache_key(func, args, kwargs) + cache_key = __get_cache_key(args, kwargs) # 尝试获取缓存 cached_value = cache_backend.get(cache_key, region=cache_region) if should_cache(cached_value) and is_valid_cache_value(cache_key, cached_value, cache_region): @@ -1010,7 +1008,7 @@ def cached(region: Optional[str] = None, maxsize: Optional[int] = 1024, ttl: Opt @wraps(func) def wrapper(*args, **kwargs): # 获取缓存键 - cache_key = cache_backend.get_cache_key(func, args, kwargs) + cache_key = __get_cache_key(args, kwargs) # 尝试获取缓存 cached_value = cache_backend.get(cache_key, region=cache_region) if should_cache(cached_value) and is_valid_cache_value(cache_key, cached_value, cache_region): diff --git a/app/helper/redis.py b/app/helper/redis.py index 0454a634..858e77bf 100644 --- a/app/helper/redis.py +++ b/app/helper/redis.py @@ -140,20 +140,32 @@ class RedisHelper(metaclass=Singleton): logger.error(f"Failed to set Redis maxmemory or policy: {e}") @staticmethod - def get_region(region: Optional[str] = "DEFAULT"): + def __get_region(region: Optional[str] = "DEFAULT"): """ 获取缓存的区 """ return f"region:{region}" if region else "region:default" - def get_redis_key(self, region: str, key: str) -> str: + def __make_redis_key(self, region: str, key: str) -> str: """ 获取缓存Key """ # 使用region作为缓存键的一部分 - region = self.get_region(quote(region)) + region = self.__get_region(quote(region)) return f"{region}:key:{quote(key)}" + @staticmethod + def __get_original_key(redis_key: str) -> str: + """ + 从Redis键中提取原始key + """ + try: + parts = redis_key.split(":key:") + return parts[-1] + except Exception as e: + logger.warn(f"Failed to parse redis key: {redis_key}, error: {e}") + return redis_key + def set(self, key: str, value: Any, ttl: Optional[int] = None, region: Optional[str] = "DEFAULT", **kwargs) -> None: """ @@ -167,7 +179,7 @@ class RedisHelper(metaclass=Singleton): """ try: self._connect() - redis_key = self.get_redis_key(region, key) + redis_key = self.__make_redis_key(region, key) # 对值进行序列化 serialized_value = serialize(value) kwargs.pop("maxsize", None) @@ -185,7 +197,7 @@ class RedisHelper(metaclass=Singleton): """ try: self._connect() - redis_key = self.get_redis_key(region, key) + redis_key = self.__make_redis_key(region, key) return self.client.exists(redis_key) == 1 except Exception as e: logger.error(f"Failed to exists key: {key} region: {region}, error: {e}") @@ -201,7 +213,7 @@ class RedisHelper(metaclass=Singleton): """ try: self._connect() - redis_key = self.get_redis_key(region, key) + redis_key = self.__make_redis_key(region, key) value = self.client.get(redis_key) if value is not None: return deserialize(value) @@ -219,7 +231,7 @@ class RedisHelper(metaclass=Singleton): """ try: self._connect() - redis_key = self.get_redis_key(region, key) + redis_key = self.__make_redis_key(region, key) self.client.delete(redis_key) except Exception as e: logger.error(f"Failed to delete key: {key} in region: {region}, error: {e}") @@ -233,7 +245,7 @@ class RedisHelper(metaclass=Singleton): try: self._connect() if region: - cache_region = self.get_region(quote(region)) + cache_region = self.__get_region(quote(region)) redis_key = f"{cache_region}:key:*" with self.client.pipeline() as pipe: for key in self.client.scan_iter(redis_key): @@ -256,17 +268,17 @@ class RedisHelper(metaclass=Singleton): try: self._connect() if region: - cache_region = self.get_region(quote(region)) + cache_region = self.__get_region(quote(region)) redis_key = f"{cache_region}:key:*" for key in self.client.scan_iter(redis_key): value = self.client.get(key) if value is not None: - yield key, deserialize(value) + yield self.__get_original_key(key), deserialize(value) else: for key in self.client.scan_iter("*"): value = self.client.get(key) if value is not None: - yield key, deserialize(value) + yield self.__get_original_key(key), deserialize(value) except Exception as e: logger.error(f"Failed to get items from Redis, region: {region}, error: {e}") @@ -367,18 +379,18 @@ class AsyncRedisHelper(metaclass=Singleton): logger.error(f"Failed to set Redis maxmemory or policy (async): {e}") @staticmethod - def get_region(region: Optional[str] = "DEFAULT"): + def __get_region(region: Optional[str] = "DEFAULT"): """ 获取缓存的区 """ return f"region:{region}" if region else "region:default" - def get_redis_key(self, region: str, key: str) -> str: + def __make_redis_key(self, region: str, key: str) -> str: """ 获取缓存Key """ # 使用region作为缓存键的一部分 - region = self.get_region(quote(region)) + region = self.__get_region(quote(region)) return f"{region}:key:{quote(key)}" async def set(self, key: str, value: Any, ttl: Optional[int] = None, @@ -394,7 +406,7 @@ class AsyncRedisHelper(metaclass=Singleton): """ try: await self._connect() - redis_key = self.get_redis_key(region, key) + redis_key = self.__make_redis_key(region, key) # 对值进行序列化 serialized_value = serialize(value) kwargs.pop("maxsize", None) @@ -412,7 +424,7 @@ class AsyncRedisHelper(metaclass=Singleton): """ try: await self._connect() - redis_key = self.get_redis_key(region, key) + redis_key = self.__make_redis_key(region, key) result = await self.client.exists(redis_key) return result == 1 except Exception as e: @@ -429,7 +441,7 @@ class AsyncRedisHelper(metaclass=Singleton): """ try: await self._connect() - redis_key = self.get_redis_key(region, key) + redis_key = self.__make_redis_key(region, key) value = await self.client.get(redis_key) if value is not None: return deserialize(value) @@ -447,7 +459,7 @@ class AsyncRedisHelper(metaclass=Singleton): """ try: await self._connect() - redis_key = self.get_redis_key(region, key) + redis_key = self.__make_redis_key(region, key) await self.client.delete(redis_key) except Exception as e: logger.error(f"Failed to delete key (async): {key} in region: {region}, error: {e}") @@ -461,7 +473,7 @@ class AsyncRedisHelper(metaclass=Singleton): try: await self._connect() if region: - cache_region = self.get_region(quote(region)) + cache_region = self.__get_region(quote(region)) redis_key = f"{cache_region}:key:*" async with self.client.pipeline() as pipe: async for key in self.client.scan_iter(redis_key): @@ -484,7 +496,7 @@ class AsyncRedisHelper(metaclass=Singleton): try: await self._connect() if region: - cache_region = self.get_region(quote(region)) + cache_region = self.__get_region(quote(region)) redis_key = f"{cache_region}:key:*" async for key in self.client.scan_iter(redis_key): value = await self.client.get(key)