diff --git a/src/quartermaster/main.py b/src/quartermaster/main.py index 30df371..43cd204 100644 --- a/src/quartermaster/main.py +++ b/src/quartermaster/main.py @@ -6,6 +6,7 @@ from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from quartermaster.routes import router +from quartermaster.routes_health import router as health_router from quartermaster.routes_month import router as month_router STATIC_DIR = Path(__file__).parent / "static" @@ -14,6 +15,7 @@ STATIC_DIR = Path(__file__).parent / "static" def create_app() -> FastAPI: app = FastAPI(title="Quartermaster", version="0.1.0") app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static") + app.include_router(health_router) app.include_router(router) app.include_router(month_router) return app diff --git a/src/quartermaster/routes_health.py b/src/quartermaster/routes_health.py new file mode 100644 index 0000000..743aac9 --- /dev/null +++ b/src/quartermaster/routes_health.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +import logging + +from fastapi import APIRouter, Depends +from fastapi.responses import JSONResponse +from sqlalchemy import text +from sqlalchemy.orm import Session + +from quartermaster.db import get_session + +logger = logging.getLogger("quartermaster.health") + +router = APIRouter() + + +@router.get("/healthz") +def healthz(db: Session = Depends(get_session)) -> JSONResponse: + try: + db.execute(text("SELECT 1")) + except Exception as exc: + logger.warning( + "healthz check failed", + extra={"event": "healthz_failed", "error_class": type(exc).__name__}, + ) + return JSONResponse( + status_code=503, + content={"status": "error", "detail": type(exc).__name__}, + ) + return JSONResponse(status_code=200, content={"status": "ok"}) diff --git a/tests/test_health.py b/tests/test_health.py new file mode 100644 index 0000000..79c973b --- /dev/null +++ b/tests/test_health.py @@ -0,0 +1,7 @@ +from __future__ import annotations + + +def test_healthz_returns_ok(client): + response = client.get("/healthz") + assert response.status_code == 200 + assert response.json() == {"status": "ok"}