@@ -119,11 +119,24 @@ Cached endpoints automatically:
119119
120120### Cache Key Structure
121121
122- Cache keys are organized by namespace for easy invalidation:
122+ Cache keys are organized by namespace for easy invalidation. Use the
123+ ` CacheNamespaces ` constants from ` app.cache.constants ` to avoid typos:
123124
125+ ``` python
126+ from app.cache.constants import CacheNamespaces
127+
128+ # Available namespaces
129+ CacheNamespaces.USER_ME # "user" - User-scoped endpoints
130+ CacheNamespaces.USERS_SINGLE # "users" - Base namespace for /users/ endpoint
131+ CacheNamespaces.USERS_LIST # "users:list" - Paginated user lists
132+ CacheNamespaces.API_KEYS_LIST # "apikeys" - User's API keys list
133+ CacheNamespaces.API_KEY_SINGLE # "apikey" - Single API key lookup
134+ ```
135+
136+ Key format patterns:
124137- ` user:{user_id} ` - User-scoped endpoints (/users/me, /users/keys)
125138- ` users:list ` - Paginated user lists
126- - ` users:{user_id}:single ` - Single user lookups
139+ - ` users:{user_id} ` - Single user lookups
127140- ` apikeys:{user_id} ` - User's API keys list
128141
129142## Configuration
@@ -197,17 +210,23 @@ Use the `@cached()` decorator on route handlers:
197210``` python
198211from fastapi import APIRouter, Request, Response
199212from app.cache import cached
213+ from app.cache.constants import CacheNamespaces
200214
201215router = APIRouter()
202216
203217@router.get (" /expensive-query" )
204- @cached (expire = 300 , namespace = " queries " )
218+ @cached (expire = 300 , namespace = CacheNamespaces. USER_ME )
205219async def expensive_query (request : Request, response : Response):
206220 # This will be cached for 5 minutes
207221 result = await perform_expensive_operation()
208222 return result
209223```
210224
225+ !!! tip "Use Namespace Constants"
226+ Always use ` CacheNamespaces ` constants instead of hardcoded strings
227+ to avoid typos and make refactoring easier. See [ Cache Key
228+ Structure] ( #cache-key-structure ) for available constants.
229+
211230!!! note "Decorator Order"
212231 The ` @cached() ` decorator MUST be placed AFTER the route decorator
213232 (` @router.get() ` , etc.) to work correctly.
@@ -236,12 +255,16 @@ For user-scoped caching, use built-in key builders:
236255
237256``` python
238257from app.cache import cached, user_scoped_key_builder
258+ from app.cache.constants import CacheNamespaces
239259from app.managers.auth import AuthManager
240260from app.models.user import User
241261
242262@router.get (" /users/me" )
243- @cached (expire = 300 , namespace = " user" ,
244- key_builder = user_scoped_key_builder)
263+ @cached (
264+ expire = 300 ,
265+ namespace = CacheNamespaces.USER_ME ,
266+ key_builder = user_scoped_key_builder,
267+ )
245268async def get_current_user (
246269 request : Request,
247270 response : Response,
@@ -267,33 +290,44 @@ The `cached()` decorator accepts these parameters:
267290The template provides helper functions to invalidate cache when data
268291changes:
269292
270- ### User Cache Invalidation
293+ ### Combined User Cache Invalidation (Recommended)
294+
295+ For user mutations (create, update, delete, ban, role changes), use the
296+ combined helper that invalidates multiple cache namespaces in parallel:
271297
272298``` python
273- from app.cache import invalidate_user_cache
299+ from app.cache import invalidate_user_related_caches
274300
275- # After updating user data
301+ # After user mutation
276302await db.commit()
277- await invalidate_user_cache (user.id)
303+ await invalidate_user_related_caches (user.id)
278304```
279305
280- This clears:
306+ This clears both user-specific and list caches concurrently using
307+ ` asyncio.gather() ` for better performance:
281308
282309- User-scoped cache (` user:{user_id} ` )
283- - Single user lookup (` users:{user_id}:single ` )
310+ - Single user lookup (` users:{user_id} ` )
311+ - Users list cache (` users:list ` )
284312
285- ### Users List Cache Invalidation
313+ ### Individual Cache Invalidation
314+
315+ For fine-grained control, you can invalidate specific cache namespaces
316+ individually:
286317
287318``` python
288- from app.cache import invalidate_users_list_cache
319+ from app.cache import (
320+ invalidate_user_cache,
321+ invalidate_users_list_cache,
322+ )
289323
290- # After creating/deleting users or changing roles
291- await db.commit()
324+ # Clear user-specific caches only
325+ await invalidate_user_cache(user.id)
326+
327+ # Clear users list only (after role changes, etc.)
292328await invalidate_users_list_cache()
293329```
294330
295- This clears all paginated user list entries.
296-
297331### API Keys Cache Invalidation
298332
299333``` python
0 commit comments