diff --git a/src/example/app.py b/src/example/app.py index 1c12356..f252a0b 100644 --- a/src/example/app.py +++ b/src/example/app.py @@ -4,6 +4,7 @@ from fastapi.responses import JSONResponse from nene2.config import AppSettings +from nene2.http import HealthStatus from nene2.middleware import ErrorHandlerMiddleware from nene2.validation.exceptions import ValidationException @@ -73,9 +74,11 @@ def create_app(settings: AppSettings | None = None) -> FastAPI: ) ) - @app.get("/health") + @app.get("/health", tags=["system"], summary="Health check") async def health() -> JSONResponse: - return JSONResponse({"status": "ok"}) + status = HealthStatus(status="ok") + code = 200 if status.is_healthy else 503 + return JSONResponse({"status": status.status, "checks": status.checks}, status_code=code) return app diff --git a/src/nene2/http/__init__.py b/src/nene2/http/__init__.py index e317ea5..02624f3 100644 --- a/src/nene2/http/__init__.py +++ b/src/nene2/http/__init__.py @@ -1,9 +1,12 @@ -"""HTTP helpers — JSON responses, pagination, problem details.""" +"""HTTP helpers — JSON responses, pagination, problem details, health.""" +from .health import HealthCheckProtocol, HealthStatus from .pagination import PaginationQuery, PaginationQueryParser, PaginationResponse from .problem_details import problem_details_response __all__ = [ + "HealthCheckProtocol", + "HealthStatus", "PaginationQuery", "PaginationQueryParser", "PaginationResponse", diff --git a/src/nene2/http/health.py b/src/nene2/http/health.py new file mode 100644 index 0000000..6690e7b --- /dev/null +++ b/src/nene2/http/health.py @@ -0,0 +1,20 @@ +"""HealthCheckProtocol and HealthStatus — framework health check contract.""" + +from dataclasses import dataclass, field +from typing import Protocol + + +@dataclass(frozen=True, slots=True) +class HealthStatus: + status: str + checks: dict[str, str] = field(default_factory=dict) + + @property + def is_healthy(self) -> bool: + return self.status == "ok" + + +class HealthCheckProtocol(Protocol): + """Contract for application health checks.""" + + def check(self) -> HealthStatus: ...