46 lines
1.5 KiB
Python
46 lines
1.5 KiB
Python
"""Liveness and readiness endpoints.
|
|
|
|
``/health/live`` answers whether the process is up. ``/health/ready`` answers
|
|
whether it can serve: the database is reachable and configured correctly (WAL,
|
|
foreign keys). Tests and any future orchestration wait on readiness rather than a
|
|
sleep. Readiness returns 503 until the checks pass.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, Request, Response
|
|
from sqlalchemy import text
|
|
|
|
router = APIRouter(tags=["health"])
|
|
|
|
|
|
@router.get("/health/live")
|
|
def live() -> dict:
|
|
return {"status": "alive"}
|
|
|
|
|
|
@router.get("/health/ready")
|
|
def ready(request: Request, response: Response) -> dict:
|
|
checks: dict[str, object] = {}
|
|
ok = True
|
|
engine = getattr(request.app.state, "engine", None)
|
|
if engine is None:
|
|
ok = False
|
|
checks["database"] = "unavailable"
|
|
else:
|
|
try:
|
|
with engine.connect() as conn:
|
|
conn.execute(text("SELECT 1"))
|
|
journal_mode = conn.execute(text("PRAGMA journal_mode")).scalar()
|
|
foreign_keys = conn.execute(text("PRAGMA foreign_keys")).scalar()
|
|
checks["database"] = "ok"
|
|
checks["journal_mode"] = journal_mode
|
|
checks["foreign_keys"] = int(foreign_keys)
|
|
if str(journal_mode).lower() != "wal" or int(foreign_keys) != 1:
|
|
ok = False
|
|
except Exception:
|
|
ok = False
|
|
checks["database"] = "error"
|
|
response.status_code = 200 if ok else 503
|
|
return {"status": "ready" if ok else "not_ready", "checks": checks}
|