"""Health + readiness probes. ``/health`` must always return 200 when the HTTP server is up (liveness). ``/health/ready`` additionally checks Mongo, RabbitMQ, Redis reachability (readiness). """ from __future__ import annotations import time from datetime import datetime, timezone from fastapi import APIRouter from pydantic import BaseModel, Field from ...config import get_settings from ...db.mongo import get_mongo_client router = APIRouter() _STARTED = time.time() class HealthResponse(BaseModel): status: str = Field(..., examples=["ok"]) service: str = "asf-core" version: str environment: str uptime_seconds: float timestamp: str @router.get("/health", response_model=HealthResponse, summary="Liveness probe") async def health() -> HealthResponse: s = get_settings() return HealthResponse( status="ok", service="asf-core", version="0.1.0", environment=s.asf_env, uptime_seconds=round(time.time() - _STARTED, 2), timestamp=datetime.now(tz=timezone.utc).isoformat().replace("+00:00", "Z"), ) class ReadyResponse(BaseModel): ready: bool checks: dict @router.get("/health/ready", response_model=ReadyResponse, summary="Readiness probe") async def ready() -> ReadyResponse: checks: dict = {} ok = True # --- MongoDB --- try: client = get_mongo_client() ping = await client.admin.command("ping") checks["mongodb"] = "ok" if ping.get("ok") else "fail" except Exception as exc: # noqa: BLE001 checks["mongodb"] = f"error: {exc}" ok = False return ReadyResponse(ready=ok, checks=checks)