generated from erangel1/generic-template
initial commit. phase 1 complete
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
"""
|
||||
Health check endpoint required by the docker-compose web service healthcheck:
|
||||
test: ["CMD-SHELL", "curl -fs http://localhost:8000/api/health/ || exit 1"]
|
||||
|
||||
Does NOT require authentication — the docker daemon calls this, not users.
|
||||
Returns HTTP 200 when all services are healthy, HTTP 503 on any failure.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.db import OperationalError, connection
|
||||
from django.http import JsonResponse
|
||||
from django.views import View
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
VERSION = "1.0.0"
|
||||
|
||||
|
||||
class HealthCheckView(View):
|
||||
"""
|
||||
Synchronous health check for web, database, and Redis.
|
||||
|
||||
Response body:
|
||||
{
|
||||
"status": "ok" | "degraded",
|
||||
"version": "1.0.0",
|
||||
"services": {
|
||||
"database": "ok" | "error",
|
||||
"redis": "ok" | "error"
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
def get(self, request) -> JsonResponse: # type: ignore[override]
|
||||
db_status = _check_database()
|
||||
redis_status = _check_redis()
|
||||
|
||||
all_ok = db_status == "ok" and redis_status == "ok"
|
||||
http_status = 200 if all_ok else 503
|
||||
|
||||
return JsonResponse(
|
||||
{
|
||||
"status": "ok" if all_ok else "degraded",
|
||||
"version": VERSION,
|
||||
"services": {
|
||||
"database": db_status,
|
||||
"redis": redis_status,
|
||||
},
|
||||
},
|
||||
status=http_status,
|
||||
)
|
||||
|
||||
|
||||
def _check_database() -> str:
|
||||
try:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("SELECT 1")
|
||||
return "ok"
|
||||
except OperationalError:
|
||||
logger.exception("Database health check failed")
|
||||
return "error"
|
||||
|
||||
|
||||
def _check_redis() -> str:
|
||||
try:
|
||||
cache.set("_health_check", "1", timeout=5)
|
||||
if cache.get("_health_check") != "1":
|
||||
raise RuntimeError("Redis round-trip failed")
|
||||
return "ok"
|
||||
except Exception:
|
||||
logger.exception("Redis health check failed")
|
||||
return "error"
|
||||
Reference in New Issue
Block a user