mengstack-api/internal/app/health/handler.go
MengStack Dev df809f1045
Some checks failed
CI / Build & Test (push) Failing after 1m31s
feat: user CRUD API + dashboard stats + kernel infrastructure
- Add user management endpoints (list/create/get/update/delete) with pagination and search
- Add dashboard stats endpoint with tenant/user/online counts and growth metrics
- Add tenant resolver middleware for multi-tenant request scoping
- Add i18n kernel with zh/en message files and AcceptLanguage middleware
- Add WebSocket hub/handler for real-time communication
- Add job scheduler kernel with cron support
- Add plugin sandbox for isolated execution
- Add storage kernel (local filesystem)
- Add event bus kernel for pub/sub
- Add cache kernel abstraction
- Add database migration runner and version upgrade checker
- Add rate limiting middleware with Redis backend
- Add SQL migrations for rbac, audit_logs, settings, notifications, examples
- Extend user repository with list/delete/count operations
- Register all module routes with tenant resolver
2026-10-03 03:42:58 +08:00

124 lines
2.9 KiB
Go
Raw Permalink 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 health
import (
"context"
"net/http"
"time"
"mengstack/internal/app/version"
"github.com/gin-gonic/gin"
"github.com/redis/go-redis/v9"
"go.uber.org/zap"
"gorm.io/gorm"
)
type Handler struct {
db *gorm.DB
rdb *redis.Client
log *zap.Logger
}
func NewHandler(db *gorm.DB, rdb *redis.Client, log *zap.Logger) *Handler {
return &Handler{db: db, rdb: rdb, log: log}
}
// Handle godoc
// @Summary 健康检查
// @Description 检查 PostgreSQL 和 Redis 连接状态
// @Tags System
// @Produce json
// @Success 200 {object} object{status=string,database=string,redis=string,timestamp=integer,version=string,trace_id=string}
// @Router /health [get]
func (h *Handler) Handle(c *gin.Context) {
status := "ok"
dbStatus := "connected"
redisStatus := "connected"
sqlDB, err := h.db.DB()
if err != nil || sqlDB.Ping() != nil {
status = "degraded"
dbStatus = "disconnected"
}
ctx, cancel := context.WithTimeout(c.Request.Context(), 2*time.Second)
defer cancel()
if h.rdb.Ping(ctx).Err() != nil {
status = "degraded"
redisStatus = "disconnected"
}
c.JSON(http.StatusOK, gin.H{
"status": status,
"database": dbStatus,
"redis": redisStatus,
"timestamp": time.Now().Unix(),
"version": version.Version,
"trace_id": c.GetString("trace_id"),
})
}
// Version godoc
// @Summary 版本信息
// @Description 返回构建版本、提交哈希、编译时间等
// @Tags System
// @Produce json
// @Success 200 {object} version.Info
// @Router /api/version [get]
func (h *Handler) Version(c *gin.Context) {
c.JSON(http.StatusOK, version.Current())
}
// Healthz godoc
// @Summary 存活探针
// @Description Kubernetes liveness probe,进程存活即返回 200
// @Tags System
// @Produce json
// @Success 200 {object} object{status=string}
// @Router /healthz [get]
func (h *Handler) Healthz(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "ok"})
}
// Readyz godoc
// @Summary 就绪探针
// @Description Kubernetes readiness probe,检查数据库和 Redis 连接
// @Tags System
// @Produce json
// @Success 200 {object} object{status=string,database=string,redis=string}
// @Failure 503 {object} object{status=string,database=string,redis=string}
// @Router /readyz [get]
func (h *Handler) Readyz(c *gin.Context) {
ctx, cancel := context.WithTimeout(c.Request.Context(), 2*time.Second)
defer cancel()
dbOK := true
sqlDB, err := h.db.DB()
if err != nil || sqlDB.Ping() != nil {
dbOK = false
}
redisOK := true
if h.rdb.Ping(ctx).Err() != nil {
redisOK = false
}
body := gin.H{
"database": boolToStatus(dbOK),
"redis": boolToStatus(redisOK),
}
if !dbOK || !redisOK {
c.JSON(http.StatusServiceUnavailable, body)
return
}
c.JSON(http.StatusOK, body)
}
func boolToStatus(ok bool) string {
if ok {
return "connected"
}
return "disconnected"
}