11import functools
22
3- from collections .abc import Callable , Sequence
3+ from collections .abc import Awaitable , Callable , Sequence
4+ from inspect import isawaitable
45from typing import Any , ParamSpec , TypeVar
56
67from msgspec import json
1617
1718P = ParamSpec ('P' )
1819T = TypeVar ('T' )
20+ _MISSING = object ()
1921
2022
21- def _build_cache_key (
22- name : str ,
23+ async def _build_cache_key (
24+ namespace : str ,
2325 key : str | None ,
24- key_builder : Callable [..., str ] | None ,
26+ key_builder : Callable [..., str | Awaitable [ str ] ] | None ,
2527 * args : Any ,
2628 ** kwargs : Any ,
2729) -> str :
2830 """构建缓存 Key"""
2931 if key :
3032 if '.' in key :
3133 param , field = key .split ('.' , 1 )
32- value = kwargs .get (param )
33- if value is None :
34- raise errors .ServerError (msg = f'缓存键构建失败,参数 "{ param } " 不存在或值为空 ' )
34+ value = kwargs .get (param , _MISSING )
35+ if value is _MISSING :
36+ raise errors .ServerError (msg = f'缓存键构建失败,参数 "{ param } " 不存在 ' )
3537
3638 if isinstance (value , list ):
3739 raise errors .ServerError (msg = '缓存键构建失败:不支持从列表中提取字段,请使用 key_builder 处理列表参数' )
@@ -43,16 +45,19 @@ def _build_cache_key(
4345 else :
4446 raise errors .ServerError (msg = f'缓存键构建失败,对象中不存在字段 "{ field } "' )
4547 else :
46- value = kwargs .get (key )
47- if value is None :
48- raise errors .ServerError (msg = f'缓存键构建失败,参数 "{ key } " 不存在或值为空 ' )
48+ value = kwargs .get (key , _MISSING )
49+ if value is _MISSING :
50+ raise errors .ServerError (msg = f'缓存键构建失败,参数 "{ key } " 不存在 ' )
4951
50- return f'{ name } :{ value } '
52+ return f'{ namespace } :{ value if value is not None else "none" } '
5153
5254 if key_builder :
53- return f'{ name } :{ key_builder (* args , ** kwargs )} '
55+ value = key_builder (* args , ** kwargs )
56+ if isawaitable (value ):
57+ value = await value
58+ return f'{ namespace } :{ value } '
5459
55- return name
60+ return namespace
5661
5762
5863def _serialize_result (result : Any ) -> bytes :
@@ -101,15 +106,15 @@ def user_key_builder() -> str:
101106
102107
103108def cached ( # noqa: C901
104- name : str ,
109+ namespace : str ,
105110 * ,
106111 key : str | None = None ,
107- key_builder : Callable [..., str ] | None = None ,
112+ key_builder : Callable [..., str | Awaitable [ str ] ] | None = None ,
108113) -> Callable [[Callable [P , T ]], Callable [P , T ]]:
109114 """
110115 缓存装饰器
111116
112- :param name: 缓存名称 (通常为缓存 Key 前缀)
117+ :param namespace: 缓存命名空间 (通常为缓存 Key 前缀)
113118 :param key: 从方法参数中获取指定参数名的值作为缓存 Key,与 key_builder 互斥
114119 :param key_builder: 自定义 Key 生成函数,与 key 互斥
115120 :return:
@@ -120,7 +125,7 @@ def cached( # noqa: C901
120125 def decorator (func : Callable [P , T ]) -> Callable [P , T ]: # noqa: C901
121126 @functools .wraps (func )
122127 async def wrapper (* args : P .args , ** kwargs : P .kwargs ) -> T :
123- cache_key = _build_cache_key (name , key , key_builder , * args , ** kwargs )
128+ cache_key = await _build_cache_key (namespace , key , key_builder , * args , ** kwargs )
124129
125130 # L1: 本地缓存
126131 if settings .CACHE_LOCAL_ENABLED :
@@ -168,16 +173,16 @@ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
168173
169174
170175def cache_invalidate ( # noqa: C901
171- name : str ,
176+ namespace : str ,
172177 * ,
173178 key : str | None = None ,
174- key_builder : Callable [..., str ] | None = None ,
179+ key_builder : Callable [..., str | Awaitable [ str ] ] | None = None ,
175180 atomic : bool = True ,
176181) -> Callable [[Callable [P , T ]], Callable [P , T ]]:
177182 """
178183 缓存失效装饰器
179184
180- :param name: 缓存名称 (通常为缓存 Key 前缀)
185+ :param namespace: 缓存命名空间 (通常为缓存 Key 前缀)
181186 :param key: 从方法参数中获取指定参数名的值作为缓存 Key,与 key_builder 互斥
182187 :param key_builder: 自定义 Key 生成函数,与 key 互斥
183188 :param atomic: 是否保证缓存原子性
@@ -196,25 +201,25 @@ async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
196201 invalidate_error = None
197202
198203 try :
199- invalidate_key = _build_cache_key (name , key , key_builder , * args , ** kwargs )
204+ invalidate_key = await _build_cache_key (namespace , key , key_builder , * args , ** kwargs )
200205
201206 # L1 缓存失效
202207 if settings .CACHE_LOCAL_ENABLED :
203- if invalidate_key == name :
204- local_cache_manager .delete_prefix (invalidate_key )
208+ if invalidate_key == namespace :
209+ local_cache_manager .delete_by_prefix (invalidate_key )
205210 else :
206211 local_cache_manager .delete (invalidate_key )
207212
208213 # 广播失效消息(通知其他节点清除本地缓存)
209214 if settings .CACHE_LOCAL_ENABLED :
210- if invalidate_key == name :
211- await cache_pubsub_manager .publish_invalidation (invalidate_key , is_delete_prefix = True )
215+ if invalidate_key == namespace :
216+ await cache_pubsub_manager .publish_invalidation (invalidate_key , delete_by_prefix = True )
212217 else :
213- await cache_pubsub_manager .publish_invalidation (invalidate_key , is_delete_prefix = False )
218+ await cache_pubsub_manager .publish_invalidation (invalidate_key , delete_by_prefix = False )
214219
215220 # L2 缓存失效
216- if invalidate_key == name :
217- await redis_client .delete_prefix (invalidate_key )
221+ if invalidate_key == namespace :
222+ await redis_client .delete_by_prefix (invalidate_key )
218223 else :
219224 await redis_client .delete (invalidate_key )
220225
0 commit comments