package handler import ( "context" "net/http" "sort" "time" "github.com/gin-gonic/gin" ) type HealthHandler struct { startedAt time.Time checks map[string]ReadinessCheck } type ReadinessCheck func(context.Context) error func NewHealthHandler(checks map[string]ReadinessCheck) *HealthHandler { return &HealthHandler{startedAt: time.Now(), checks: checks} } func (h *HealthHandler) Live(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "status": "ok", "service": "hfb-api", "started_at": h.startedAt.Format(time.RFC3339), }) } func (h *HealthHandler) Ready(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 2*time.Second) defer cancel() names := make([]string, 0, len(h.checks)) for name := range h.checks { names = append(names, name) } sort.Strings(names) ready := true dependencies := make(map[string]string, len(names)) for _, name := range names { check := h.checks[name] if check == nil || check(ctx) != nil { dependencies[name] = "unavailable" ready = false continue } dependencies[name] = "ok" } statusCode := http.StatusOK status := "ok" if !ready { statusCode = http.StatusServiceUnavailable status = "unavailable" } c.JSON(statusCode, gin.H{ "status": status, "service": "hfb-api", "started_at": h.startedAt.Format(time.RFC3339), "dependencies": dependencies, }) }