"""Platform health probes (P0.4). Exposes unauthenticated ``/api/health`` (quick liveness) and ``/api/health/ready`` (deep readiness: DB + JWT secret + OpenAI key). Designed to be consumed by uptime monitors, load-balancer health checks and container orchestrators. """ import logging import time from odoo import http from odoo.http import request from odoo.release import version as odoo_version _logger = logging.getLogger(__name__) _STARTED_AT = time.time() class HealthController(http.Controller): """Platform health probes — safe to expose publicly.""" @http.route("/api/health", type="http", auth="none", methods=["GET"], csrf=False) def health(self, **_kw): """Liveness probe: the process is up and able to handle HTTP.""" return request.make_json_response({ "status": "ok", "service": "encoach-backend", "odoo_version": odoo_version, "uptime_seconds": int(time.time() - _STARTED_AT), }) @http.route("/api/health/ready", type="http", auth="none", methods=["GET"], csrf=False) def ready(self, **_kw): """Readiness probe: DB reachable, JWT secret configured, AI key known.""" checks = {} ok = True try: request.env.cr.execute("SELECT 1") checks["database"] = "ok" except Exception as exc: ok = False checks["database"] = f"error: {exc}" try: IrParam = request.env["ir.config_parameter"].sudo() checks["jwt_secret"] = "ok" if IrParam.get_param("encoach.jwt_secret") else "missing" if checks["jwt_secret"] == "missing": ok = False ai_key = IrParam.get_param("encoach_ai.openai_api_key") import os if not ai_key: ai_key = os.environ.get("OPENAI_API_KEY", "") checks["openai_key"] = "ok" if ai_key else "missing" except Exception as exc: ok = False checks["config"] = f"error: {exc}" status = 200 if ok else 503 return request.make_json_response({ "status": "ok" if ok else "degraded", "checks": checks, "uptime_seconds": int(time.time() - _STARTED_AT), }, status=status)