66 lines
1.6 KiB
Python
66 lines
1.6 KiB
Python
"""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)
|