Coverage for baibu/core/views.py: 100%
43 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-10-06 13:07 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-10-06 13:07 +0000
1import logging
2from datetime import datetime
4from django.conf import settings
5from django.core.cache import cache
6from django.db import connection
7from django.http import HttpRequest
8from django.http import JsonResponse
9from django.utils import timezone
10from django.views.decorators.cache import never_cache
12from .tasks import HEARTBEAT_CACHE_KEY
14logger = logging.getLogger(__name__)
17def _check_database() -> bool:
18 try:
19 with connection.cursor() as cursor:
20 cursor.execute("SELECT 1")
21 cursor.fetchone()
22 except Exception:
23 logger.exception("Health check: database unavailable")
24 return False
25 return True
28def _check_cache() -> bool:
29 try:
30 cache.set("core:health-probe", "ok", timeout=10)
31 return cache.get("core:health-probe") == "ok"
32 except Exception:
33 logger.exception("Health check: cache unavailable")
34 return False
37def _worker_status() -> str:
38 """``ok`` if a worker ran the heartbeat task recently, else ``stale`` or ``unknown``."""
39 value = cache.get(HEARTBEAT_CACHE_KEY)
40 if not value:
41 return "unknown"
42 try:
43 last_beat = datetime.fromisoformat(value)
44 except (TypeError, ValueError):
45 return "unknown"
46 age = (timezone.now() - last_beat).total_seconds()
47 return "ok" if age <= settings.WORKER_HEARTBEAT_STALE_SECONDS else "stale"
50@never_cache
51def health(request: HttpRequest) -> JsonResponse:
52 """Liveness for operators and container health checks.
54 Returns 503 when the database or cache is down. The worker status is
55 reported but does not fail the check, so the web container is not
56 restarted because a worker is down.
57 """
58 database_ok = _check_database()
59 cache_ok = _check_cache()
60 healthy = database_ok and cache_ok
61 return JsonResponse(
62 {
63 "status": "ok" if healthy else "error",
64 "database": "ok" if database_ok else "error",
65 "cache": "ok" if cache_ok else "error",
66 "worker": _worker_status(),
67 },
68 status=200 if healthy else 503,
69 )