package api import ( "encoding/json" "net/http" "time" ) // HealthStatus represents the health status of the service type HealthStatus struct { Timestamp time.Time `json:"timestamp"` Checks map[string]string `json:"checks,omitempty"` Status string `json:"status"` } // HealthHandler handles /health requests type HealthHandler struct { server *Server } // NewHealthHandler creates a new health check handler func NewHealthHandler(s *Server) *HealthHandler { return &HealthHandler{server: s} } // Health performs a basic health check func (h *HealthHandler) Health(w http.ResponseWriter, r *http.Request) { status := HealthStatus{ Status: "healthy", Timestamp: time.Now().UTC(), Checks: make(map[string]string), } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) _ = json.NewEncoder(w).Encode(status) } // Liveness performs a liveness probe (is the service running?) func (h *HealthHandler) Liveness(w http.ResponseWriter, r *http.Request) { // Simple liveness check - if we can respond, we're alive status := HealthStatus{ Status: "alive", Timestamp: time.Now().UTC(), } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) _ = json.NewEncoder(w).Encode(status) } // Readiness performs a readiness probe (is the service ready to accept traffic?) func (h *HealthHandler) Readiness(w http.ResponseWriter, r *http.Request) { status := HealthStatus{ Status: "ready", Timestamp: time.Now().UTC(), Checks: make(map[string]string), } // Check Redis connection (if queue is configured) if h.server.taskQueue != nil { // Simple check - if queue exists, assume it's ready status.Checks["queue"] = "ok" } // Check experiment manager if h.server.expManager != nil { status.Checks["experiments"] = "ok" } // If all checks pass, we're ready w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) _ = json.NewEncoder(w).Encode(status) } // RegisterHealthRoutes registers health check routes func (h *HealthHandler) RegisterRoutes(mux *http.ServeMux) { mux.HandleFunc("/health", h.Health) mux.HandleFunc("/health/live", h.Liveness) mux.HandleFunc("/health/ready", h.Readiness) }