33import json
44from uuid import UUID
55from datetime import datetime
6+ import re
67
78from fastapi import Request , Response
89from redis .asyncio import Redis , ConnectionPool
@@ -86,11 +87,75 @@ def _infer_resource_id(kwargs: Dict[str, Any], resource_id_type: Union[type, str
8687 return resource_id
8788
8889
89- def cache (key_prefix : str , resource_id_name : Any = None , expiration : int = 3600 , resource_id_type : Union [type , List [type ]] = int ) -> Callable :
90+ def _extract_data_inside_brackets (input_string : str ) -> List [str ]:
91+ # Use regular expressions to find data inside brackets
92+ data_inside_brackets = re .findall (r'{(.*?)}' , input_string )
93+ return data_inside_brackets
94+
95+
96+ def _format_prefix (prefix : str , kwargs : Dict [str , Any ]) -> str :
97+ """
98+ Format a prefix using keyword arguments.
99+
100+ Parameters
101+ ----------
102+ prefix: str
103+ The prefix template to be formatted.
104+ kwargs: Dict[str, Any]
105+ A dictionary of keyword arguments.
106+
107+ Returns
108+ -------
109+ str: The formatted prefix.
110+ """
111+ data_inside_brackets = _extract_data_inside_brackets (prefix )
112+ formatted_prefix = prefix .format (** {key : kwargs [key ] for key in data_inside_brackets })
113+ return formatted_prefix
114+
115+
116+ def _format_extra_data (
117+ to_invalidate_extra : Dict [str , str ],
118+ kwargs : Dict [str , Any ]
119+ ) -> Dict [str , Any ]:
120+ """
121+ Format extra data based on provided templates and keyword arguments.
122+
123+ This function takes a dictionary of templates and their associated values and a dictionary of keyword arguments.
124+ It formats the templates with the corresponding values from the keyword arguments and returns a dictionary
125+ where keys are the formatted templates and values are the associated keyword argument values.
126+
127+ Parameters
128+ ----------
129+ to_invalidate_extra: Dict[str, str]
130+ A dictionary where keys are templates and values are the associated values.
131+ kwargs: Dict[str, Any]
132+ A dictionary of keyword arguments.
133+
134+ Returns
135+ -------
136+ Dict[str, Any]: A dictionary where keys are formatted templates and values are associated keyword argument values.
137+ """
138+ formatted_extra = {}
139+ for prefix , id_template in to_invalidate_extra .items ():
140+ formatted_prefix = _format_prefix (prefix , kwargs )
141+ id = _extract_data_inside_brackets (id_template )[0 ]
142+ formatted_extra [formatted_prefix ] = kwargs [id ]
143+
144+ return formatted_extra
145+
146+
147+ def cache (
148+ key_prefix : str ,
149+ resource_id_name : Any = None ,
150+ expiration : int = 3600 ,
151+ resource_id_type : Union [type , List [type ]] = int ,
152+ to_invalidate_extra : Dict [str , Any ] | None = None
153+ ) -> Callable :
90154 """
91155 Cache decorator for FastAPI endpoints.
92156
93- This decorator allows you to cache the results of FastAPI endpoint functions, improving response times and reducing the load on the application by storing and retrieving data in a cache.
157+ This decorator allows you to cache the results of FastAPI endpoint functions, improving response times and
158+ reducing the load on the application by storing and retrieving data in a cache.
94159
95160 Parameters
96161 ----------
@@ -140,7 +205,8 @@ async def inner(request: Request, *args, **kwargs) -> Response:
140205 else :
141206 resource_id = _infer_resource_id (kwargs = kwargs , resource_id_type = resource_id_type )
142207
143- cache_key = f"{ key_prefix } :{ resource_id } "
208+ formatted_key_prefix = _format_prefix (key_prefix , kwargs )
209+ cache_key = f"{ formatted_key_prefix } :{ resource_id } "
144210
145211 if request .method == "GET" :
146212 cached_data = await client .get (cache_key )
@@ -163,6 +229,11 @@ async def inner(request: Request, *args, **kwargs) -> Response:
163229 await client .expire (cache_key , expiration )
164230 else :
165231 await client .delete (cache_key )
232+ if to_invalidate_extra :
233+ formatted_extra = _format_extra_data (to_invalidate_extra , kwargs )
234+ for prefix , id in formatted_extra .items ():
235+ extra_cache_key = f"{ prefix } :{ id } "
236+ await client .delete (extra_cache_key )
166237
167238 return result
168239
0 commit comments