Files
leocrm/app/routes/health.py
T

82 lines
2.3 KiB
Python

"""Health check endpoints — liveness, readiness, and full health.
/health/live — process is alive (always 200 if running)
/health/ready — ready to serve requests (checks DB, Redis, storage)
/api/v1/health — full health with all checks (backward compatible)
"""
from __future__ import annotations
from fastapi import APIRouter
from pydantic import BaseModel
from app.core.monitoring import get_health_status
from app.schemas.common import HealthResponse
router = APIRouter(tags=["health"])
class LiveResponse(BaseModel):
status: str = "alive"
class ReadyResponse(BaseModel):
status: str # "ready" or "not_ready"
checks: dict[str, str] = {}
@router.get("/health/live")
async def health_live() -> LiveResponse:
"""Liveness probe — process is alive.
Returns 200 if the process is running.
Used by Kubernetes/Coolify for restart decisions.
"""
return LiveResponse(status="alive")
@router.get("/health/ready")
async def health_ready() -> ReadyResponse:
"""Readiness probe — ready to serve requests.
Checks:
- PostgreSQL connection
- Redis connection
- Storage backend
- Worker heartbeat (if available)
Returns 200 if all checks pass, 503 if any fail.
Used by load balancer to route traffic.
"""
health = await get_health_status()
checks = {}
all_ready = True
# health is a dict (or HealthResponse), handle both
health_checks = health.get('checks', {}) if isinstance(health, dict) else (health.checks or {})
for check_name, check_val in health_checks.items():
# Handle both string status and dict with status key
if isinstance(check_val, dict):
status_val = check_val.get("status", "unknown")
else:
status_val = str(check_val)
status = "ok" if status_val in ("ok", "up", "healthy", "true", "True") else "fail"
checks[check_name] = status
if status != "ok":
all_ready = False
return ReadyResponse(
status="ready" if all_ready else "not_ready",
checks=checks,
)
@router.get("/api/v1/health", response_model=HealthResponse)
async def health():
"""Full health check — no auth required.
Returns status (healthy/degraded) and individual checks for
database, redis, storage, and worker.
"""
return await get_health_status()