Source code for alchemiq.fastapi.health

"""Health-check routes. Requires the ``[fastapi]`` extra.

``/ready`` probes configured backends (k8s readinessProbe); ``/live`` is a dependency-free
liveness signal (k8s livenessProbe).
"""

from fastapi import APIRouter, Response

from alchemiq.health import check_health


[docs] def health_router( *, prefix: str = "/health", timeout: float = 5.0, include_liveness: bool = True ) -> APIRouter: """Build an ``APIRouter`` with ``GET /ready`` and optionally ``GET /live`` endpoints. ``GET /ready`` calls :func:`.check_health` and returns 200 when all components are healthy or 503 when any component is degraded - suitable for a Kubernetes ``readinessProbe``. ``GET /live`` always returns 200 with ``{"status": "alive"}`` and has no backend dependencies - suitable for a Kubernetes ``livenessProbe``. E.g.:: from fastapi import FastAPI from alchemiq.fastapi import health_router app = FastAPI() app.include_router(health_router()) # custom prefix: app.include_router(health_router(prefix="/probe")) # readiness only - omit the /live route: app.include_router(health_router(include_liveness=False)) :param prefix: URL prefix for the health routes (default ``"/health"``). :param timeout: seconds passed to :func:`.check_health` for backend probes (default ``5.0``). :param include_liveness: when ``False``, the ``GET /live`` route is omitted. :return: a configured ``APIRouter`` ready to pass to ``app.include_router()``. .. seealso:: :func:`.check_health` - the underlying health probe implementation. """ router = APIRouter(prefix=prefix, tags=["health"]) @router.get("/ready") async def ready(response: Response) -> dict[str, object]: report = await check_health(timeout=timeout) response.status_code = 200 if report.healthy else 503 return report.to_dict() if include_liveness: @router.get("/live") async def live() -> dict[str, str]: return {"status": "alive"} return router