Files
BackupX/server/internal/http/health_handler.go
T
Awuqing c06bbec383 refactor: simplify architecture and harden lifecycle
Remove obsolete implementations, centralize background task ownership and terminal-state recovery, consolidate frontend routing and log streaming, and enforce project-wide verification in CI.
2026-08-26 11:32:00 +08:00

74 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package http
import (
stdhttp "net/http"
"time"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// HealthHandler 提供 K8s/Swarm 风格的健康检查端点。
//
// - /health liveness 探针。进程存活即 200(不检查任何依赖)。
// - /ready readiness 探针。检查数据库连通,不通则返回 503。
//
// 两者均为公开端点(无认证中间件),供外部编排系统探测。
// 输出最少信息,避免泄露内部结构。
type HealthHandler struct {
db *gorm.DB
startedAt time.Time
version string
}
func NewHealthHandler(db *gorm.DB, version string) *HealthHandler {
return &HealthHandler{db: db, startedAt: time.Now().UTC(), version: version}
}
// Live 用于 liveness:只要进程能响应就返回 200。
func (h *HealthHandler) Live(c *gin.Context) {
c.JSON(stdhttp.StatusOK, gin.H{
"status": "live",
"version": h.version,
"uptime": int(time.Since(h.startedAt).Seconds()),
"timestamp": time.Now().UTC().Format(time.RFC3339),
})
}
// Ready 用于 readiness:依赖(数据库)不可用时返回 503。
// 新实例启动或数据库短暂失联时,编排系统据此停止转发流量。
func (h *HealthHandler) Ready(c *gin.Context) {
checks := map[string]string{}
overallOK := true
if h.db != nil {
sqlDB, err := h.db.DB()
if err != nil {
checks["database"] = "error: " + err.Error()
overallOK = false
} else {
if err := sqlDB.PingContext(c.Request.Context()); err != nil {
checks["database"] = "ping failed: " + err.Error()
overallOK = false
} else {
checks["database"] = "ok"
}
}
} else {
checks["database"] = "not configured"
overallOK = false
}
status := stdhttp.StatusOK
state := "ready"
if !overallOK {
status = stdhttp.StatusServiceUnavailable
state = "not_ready"
}
c.JSON(status, gin.H{
"status": state,
"version": h.version,
"uptime": int(time.Since(h.startedAt).Seconds()),
"checks": checks,
"timestamp": time.Now().UTC().Format(time.RFC3339),
})
}