Skip to content

Commit 9e92b88

Browse files
committed
docs: update caching guide for namespace constants and parallel invalidation
- Add CacheNamespaces constants reference to avoid hardcoded strings - Update examples to show invalidate_user_related_caches() for parallel invalidation instead of sequential calls - Add tip recommending use of namespace constants - Update all code examples to use best practices Relates to PR #814 (namespace constants) and PR #815 (parallel invalidation)
1 parent 808edbc commit 9e92b88

1 file changed

Lines changed: 51 additions & 17 deletions

File tree

docs/usage/caching.md

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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
198211
from fastapi import APIRouter, Request, Response
199212
from app.cache import cached
213+
from app.cache.constants import CacheNamespaces
200214

201215
router = APIRouter()
202216

203217
@router.get("/expensive-query")
204-
@cached(expire=300, namespace="queries")
218+
@cached(expire=300, namespace=CacheNamespaces.USER_ME)
205219
async 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
238257
from app.cache import cached, user_scoped_key_builder
258+
from app.cache.constants import CacheNamespaces
239259
from app.managers.auth import AuthManager
240260
from 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+
)
245268
async def get_current_user(
246269
request: Request,
247270
response: Response,
@@ -267,33 +290,44 @@ The `cached()` decorator accepts these parameters:
267290
The template provides helper functions to invalidate cache when data
268291
changes:
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
276302
await 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.)
292328
await 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

Comments
 (0)