package service import ( "context" "database/sql" "time" "github.com/redis/go-redis/v9" ) // HealthChecker provides health check functionality for dependencies type HealthChecker struct { db *sql.DB redisClient *redis.Client } // NewHealthChecker creates a new health checker instance func NewHealthChecker(db *sql.DB, redisClient *redis.Client) *HealthChecker { return &HealthChecker{ db: db, redisClient: redisClient, } } // CheckDatabase checks if the database connection is healthy func (h *HealthChecker) CheckDatabase() bool { if h.db == nil { return false } ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() var result int err := h.db.QueryRowContext(ctx, "SELECT 1").Scan(&result) if err != nil { return false } return result == 1 } // CheckRedis checks if the Redis connection is healthy func (h *HealthChecker) CheckRedis() bool { if h.redisClient == nil { return false } ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() err := h.redisClient.Ping(ctx).Err() return err == nil } // GetDatabaseStats returns database connection statistics func (h *HealthChecker) GetDatabaseStats() (active, idle int) { if h.db == nil { return 0, 0 } stats := h.db.Stats() return stats.InUse, stats.Idle } // GetRedisStats returns Redis connection statistics func (h *HealthChecker) GetRedisStats() (total, idle int) { if h.redisClient == nil { return 0, 0 } stats := h.redisClient.PoolStats() if stats == nil { return 0, 0 } return int(stats.TotalConns), int(stats.IdleConns) } // HealthStatus represents the health status of all dependencies type HealthStatus struct { Database DatabaseHealth `json:"database"` Redis RedisHealth `json:"redis"` } // DatabaseHealth represents database health information type DatabaseHealth struct { Healthy bool `json:"healthy"` ActiveConns int `json:"active_connections"` IdleConns int `json:"idle_connections"` OpenConns int `json:"open_connections"` MaxOpenConns int `json:"max_open_connections"` WaitCount int64 `json:"wait_count"` MaxIdleClosed int64 `json:"max_idle_closed"` MaxLifetimeClosed int64 `json:"max_lifetime_closed"` } // RedisHealth represents Redis health information type RedisHealth struct { Healthy bool `json:"healthy"` TotalConns int `json:"total_connections"` IdleConns int `json:"idle_connections"` } // GetHealthStatus returns comprehensive health status func (h *HealthChecker) GetHealthStatus() HealthStatus { status := HealthStatus{} // Database health status.Database.Healthy = h.CheckDatabase() if h.db != nil { stats := h.db.Stats() status.Database.ActiveConns = stats.InUse status.Database.IdleConns = stats.Idle status.Database.OpenConns = stats.OpenConnections status.Database.MaxOpenConns = stats.MaxOpenConnections status.Database.WaitCount = stats.WaitCount status.Database.MaxIdleClosed = stats.MaxIdleClosed status.Database.MaxLifetimeClosed = stats.MaxLifetimeClosed } // Redis health status.Redis.Healthy = h.CheckRedis() if h.redisClient != nil { stats := h.redisClient.PoolStats() if stats != nil { status.Redis.TotalConns = int(stats.TotalConns) status.Redis.IdleConns = int(stats.IdleConns) } } return status }