- Environment-split settings: base/local/test/prod with django-environ - Postgres + Redis + Celery wiring (broker, beat, result backend) - All 9 domain app stubs: accounts, courses, cms, tracking, quizzes, training, certificates, reports, notifications - api app: /healthz/ endpoint, custom DRF exception handler, SecurityAuditMiddleware, permissions/throttle/upload-validation stubs - DRF global baseline: JWT+session auth, closed-by-default permissions, cursor/page pagination, drf-spectacular schema generation - Dockerfile (multi-env build arg), docker-compose.yml (local), docker-compose.test.yml (CI-friendly tmpfs Postgres) - pytest.ini with smoke + settings marker definitions - tests/test_smoke.py: startup, URL resolution, healthcheck shape - tests/test_settings_matrix.py: per-profile security assertions - .github/workflows/ci.yml: test, lint, schema CI jobs - .env.example with all required vars documented - .gitignore Co-Authored-By: Paperclip <noreply@paperclip.ing>
41 lines
1.2 KiB
Python
41 lines
1.2 KiB
Python
import time
|
|
from django.db import connection, OperationalError
|
|
from django.core.cache import cache
|
|
from rest_framework.decorators import api_view, permission_classes, authentication_classes
|
|
from rest_framework.permissions import AllowAny
|
|
from rest_framework.response import Response
|
|
from rest_framework import status
|
|
|
|
|
|
@api_view(["GET"])
|
|
@authentication_classes([])
|
|
@permission_classes([AllowAny])
|
|
def healthcheck(request):
|
|
"""Liveness + readiness probe endpoint. Returns 200 when all dependencies are reachable."""
|
|
checks = {}
|
|
overall_ok = True
|
|
|
|
# Database
|
|
try:
|
|
connection.ensure_connection()
|
|
checks["db"] = "ok"
|
|
except OperationalError as exc:
|
|
checks["db"] = f"error: {exc}"
|
|
overall_ok = False
|
|
|
|
# Cache / Redis
|
|
try:
|
|
key = "_healthcheck"
|
|
cache.set(key, "1", timeout=5)
|
|
assert cache.get(key) == "1"
|
|
checks["cache"] = "ok"
|
|
except Exception as exc:
|
|
checks["cache"] = f"error: {exc}"
|
|
overall_ok = False
|
|
|
|
http_status = status.HTTP_200_OK if overall_ok else status.HTTP_503_SERVICE_UNAVAILABLE
|
|
return Response(
|
|
{"status": "ok" if overall_ok else "degraded", "checks": checks},
|
|
status=http_status,
|
|
)
|