Files
photoanalyzer/photo_pipeline/api/routes/health.py

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}