Use Case 11: Proper Cache Lifecycle in FastAPI
Scenario:
A microservice uses InMemoryCacheBackend (or Redis) and needs to start the cache cleanup task when the app starts, then shut it down cleanly on termination.
📦 What’s New?
| Component | Description |
|---|---|
ModelRegistry.initialize_cache() |
Starts the async background task for the registered cache backend. |
ModelRegistry.shutdown_cache() |
Gracefully stops the background task and releases resources. |
| FastAPI lifespan integration | Demonstrates where to call both init and shutdown methods. |
🚀 Example
Python
from mongo_ops import MongoConnectionManager, ModelRegistry
from mongo_ops.cache import InMemoryCacheBackend
from contextlib import asynccontextmanager
# Initialise a cache backend (in‑memory example)
cache = InMemoryCacheBackend(max_entries=10_000, default_ttl=300)
ModelRegistry.set_cache_backend(cache)
@asynccontextmanager
async def lifespan(app):
# Start MongoDB connection and cache background task
async with MongoConnectionManager.lifespan(
uri="mongodb://localhost:27017",
db_name="mydb",
):
await ModelRegistry.initialize_all() # create indexes
await ModelRegistry.initialize_cache() # start cache cleanup
yield
# FastAPI will exit the `with` block here – clean up cache
await ModelRegistry.shutdown_cache()
Why a separate shutdown step?
- The cache backend may spawn an
asyncio.Taskthat periodically removes expired entries. If the task is left dangling, the event loop may complain about pending tasks on shutdown. shutdown_cache()cancels the internal task and waits for it to finish, ensuring a clean exit.
💡 Tips
- Register the cache before calling
initialize_cache(); otherwise the registry won’t know which backend to start. - For Redis backends, the shutdown step also closes the underlying
redis.asyncio.Redisclient connection. - You can also hook the shutdown into a FastAPI
@app.on_event("shutdown")handler if you prefer not to use the lifespan context manager.