package handler import ( "context" "errors" "net/http" "time" "carrotskin/pkg/redis" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // NewHealthCheck 构造健康检查 handler,依赖通过参数注入。 func NewHealthCheck(db *gorm.DB, redisClient *redis.Client) gin.HandlerFunc { return func(c *gin.Context) { ctx, cancel := context.WithTimeout(c.Request.Context(), 5*time.Second) defer cancel() checks := make(map[string]string) status := "ok" // 检查数据库 if err := checkDatabase(ctx, db); err != nil { checks["database"] = "unhealthy: " + err.Error() status = "degraded" } else { checks["database"] = "healthy" } // 检查Redis if err := checkRedis(ctx, redisClient); err != nil { checks["redis"] = "unhealthy: " + err.Error() status = "degraded" } else { checks["redis"] = "healthy" } // 根据状态返回相应的HTTP状态码 httpStatus := http.StatusOK if status == "degraded" { httpStatus = http.StatusServiceUnavailable } c.JSON(httpStatus, gin.H{ "status": status, "message": "CarrotSkin API health check", "checks": checks, "timestamp": time.Now().Unix(), }) } } // checkDatabase 检查数据库连接 func checkDatabase(ctx context.Context, db *gorm.DB) error { if db == nil { return errors.New("数据库未初始化") } sqlDB, err := db.DB() if err != nil { return err } // 使用Ping检查连接 if err := sqlDB.PingContext(ctx); err != nil { return err } // 执行简单查询验证 var result int if err := db.WithContext(ctx).Raw("SELECT 1").Scan(&result).Error; err != nil { return err } return nil } // checkRedis 检查Redis连接 func checkRedis(ctx context.Context, client *redis.Client) error { if client == nil { return errors.New("Redis客户端未初始化") } // 使用Ping检查连接(封装后的方法直接返回error) if err := client.Ping(ctx); err != nil { return err } return nil }