Files
crm-system/app/api/v1/health.py
T

70 lines
1.8 KiB
Python
Raw Normal View History

2026-06-03 23:52:13 +00:00
"""Health check endpoints: /health (root) and /api/v1/health."""
from __future__ import annotations
import logging
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession
from app import __version__
from app.core.db import get_db
logger = logging.getLogger(__name__)
router = APIRouter(tags=["health"])
async def _check_db(db: AsyncSession) -> bool:
"""Run SELECT 1 to verify the database connection is alive."""
try:
result = await db.execute(text("SELECT 1"))
result.scalar_one()
return True
except Exception as e:
logger.error("Database health check failed: %s", e)
return False
@router.get(
"/health",
summary="Healthcheck (used by Coolify + Kubernetes)",
)
async def health(
db: AsyncSession = Depends(get_db),
) -> dict:
"""Returns 200 if the API and DB are healthy, 503 if the DB is down."""
db_ok = await _check_db(db)
if not db_ok:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail={"status": "error", "db": "down"},
)
return {
"status": "ok",
"db": "ok",
"version": __version__,
}
@router.get(
"/api/v1/health",
summary="Versioned healthcheck (for clients that hit /api/v1/*)",
)
async def api_v1_health(
db: AsyncSession = Depends(get_db),
) -> dict:
"""Same as /health but under the /api/v1 prefix for versioned routing."""
db_ok = await _check_db(db)
if not db_ok:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail={"status": "error", "db": "down"},
)
return {
"status": "ok",
"db": "ok",
"version": __version__,
}