Context Manager
FastAPI Maintenance provides an async context manager that temporarily enables maintenance mode and automatically restores the previous state when done. This approach is ideal for critical tasks where you need temporary downtime without manually toggling maintenance settings, such as:
- Database migrations
- Application deployments
- Data imports or exports
- Content synchronization and updates
- System updates
- User permission and role updates
- Rolling out new features
- Temporarily disabling services during critical operations
Basic Usage
The maintenance_mode_on
context manager temporarily enables maintenance mode and automatically restores the previous state when exiting the context:
from fastapi import FastAPI
from fastapi_maintenance import MaintenanceModeMiddleware, maintenance_mode_on
app = FastAPI()
app.add_middleware(MaintenanceModeMiddleware)
@app.post("/admin/sync")
async def sync_data():
# Temporarily enable maintenance mode during data sync
async with maintenance_mode_on():
# Data sync logic here
await perform_sync()
# When this block finishes, maintenance mode is automatically disabled
return {"status": "completed"}
How It Works With Different Backends
The context manager works with all backend types, but behaves differently depending on the backend's characteristics:
Local File Backend
When using a writable backend like LocalFileBackend
, the context manager:
1. Reads the current maintenance state
2. Sets maintenance mode to ON
3. Executes your code within the context
4. Restores the original state when exiting
from fastapi import FastAPI
from fastapi_maintenance import MaintenanceModeMiddleware, maintenance_mode_on
from fastapi_maintenance.backends import LocalFileBackend
app = FastAPI()
app.add_middleware(
MaintenanceModeMiddleware,
backend=LocalFileBackend(file_path="maintenance_mode.txt"),
)
@app.post("/admin/run-migration")
async def run_migration():
async with maintenance_mode_on():
# The maintenance_mode.txt file is updated to enable maintenance
await perform_database_migration()
# When done, the file is restored to its original state
return {"migration": "completed"}
Environment Variable Backend
When using the default environment variable backend (which is read-only), the context manager: 1. Creates a temporary in-memory override to enable maintenance mode 2. Executes your code within the context 3. Removes the override when exiting
from fastapi import FastAPI
from fastapi_maintenance import MaintenanceModeMiddleware, maintenance_mode_on
# Using default environment variable backend
app = FastAPI()
app.add_middleware(MaintenanceModeMiddleware)
@app.post("/admin/update")
async def update_system():
# Even though environment variables can't be changed at runtime,
# this still works using an in-memory override
async with maintenance_mode_on():
# System enters maintenance mode
await perform_update()
# Maintenance mode is disabled when the context exits
return {"update": "completed"}
Note: The environment variable itself is never modified, but the maintenance mode is still effectively enabled for the duration of the context block.
Using With Custom Backend
You can also specify a custom backend when using the context manager:
from fastapi_maintenance import maintenance_mode_on
from fastapi_maintenance.backends import LocalFileBackend
# Create a specific backend instance
custom_backend = LocalFileBackend(file_path="/path/to/custom_file.txt")
async def custom_maintenance_operation():
# Use the specific backend with the context manager
async with maintenance_mode_on(backend=custom_backend):
# This only affects the custom_backend, not the globally configured one
await perform_maintenance_tasks()
Nesting Context Managers
You can nest the maintenance_mode_on
context manager. When nesting, the innermost context will maintain the state established by the outer context:
async def complex_operation():
# Start with maintenance OFF
assert not await get_maintenance_mode()
async with maintenance_mode_on():
# Now maintenance is ON
assert await get_maintenance_mode()
# Nested context - maintenance stays ON
async with maintenance_mode_on():
# Still ON
assert await get_maintenance_mode()
await perform_nested_task()
# After inner context - still ON
assert await get_maintenance_mode()
# After outer context - back to OFF
assert not await get_maintenance_mode()
The maintenance state will only be restored to its original value when all nested contexts are exited.