Files
xlgo-core/database/redis.go
T
杭州明婳科技 0c9f256dfc feat(v1.1.0): HA & Manager 化
对应体检报告 #10-#24,一次性完成 v1.1.0 全部 13 项:

- #10 storage/cache/redis/jwt/logger 五组件 Manager 化(XxxManager + DefaultXxx + SetDefaultXxxManager,包级 facade 保留兼容)
- #11 删除 wire 包 + 清理 StartServerWithPort/GracefulShutdown 双轨
- #12 Lifecycle Hooks(OnInit/OnStart/OnReady/OnStop)
- #13 Server 参数配置化(timeout/TLS/unix_socket/response_mode)
- #14 JWTConfig.Expire 改 time.Duration + 删 AppConfig.TokenExpire
- #15 response Mode 开关(ModeBusiness/ModeREST)
- #16 Config.Validate 启动期校验
- #17 livez/readyz 探针路由
- #18 Prometheus metrics 中间件 + /metrics
- #19 请求级 Timeout 中间件
- #21 主库探活 + replica 健康剔除
- #22 App.Go + in-flight goroutine 管理
- #24 RequestID 默认装入 + #23 核对

Breaking:删 wire、删 TokenExpire、JWTConfig.Expire 类型变更、删双轨函数。
详见 CHANGELOG 升级说明。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 10:41:05 +08:00

118 lines
2.8 KiB
Go

package database
import (
"context"
"fmt"
"sync"
"github.com/EthanCodeCraft/xlgo-core/config"
"github.com/EthanCodeCraft/xlgo-core/logger"
"github.com/redis/go-redis/v9"
"go.uber.org/zap"
)
// RedisClient 全局 Redis 客户端(兼容 facade,由 RedisManager.Init 同步维护)。
// 保留供存量代码直接访问;新代码建议用 GetRedis() 或持有 *RedisManager 实例。
var RedisClient *redis.Client
// RedisManager Redis 连接管理器(#10)。照 database.Manager 模式:
// 实例化 + DefaultRedis 全局默认 + 包级 facade 代理,支持多实例与测试注入。
type RedisManager struct {
mu sync.Mutex
cfg *config.Config
client *redis.Client
}
// DefaultRedis 默认 Redis 管理器,包级 facade 代理到它。
var DefaultRedis = NewRedisManager()
// NewRedisManager 创建 Redis 管理器实例。
func NewRedisManager() *RedisManager { return &RedisManager{} }
// SetDefaultRedisManager 提升指定 RedisManager 为全局默认,后续包级 facade 走它。
// 用于多实例场景或测试注入 mock。
func SetDefaultRedisManager(m *RedisManager) {
if m != nil {
DefaultRedis = m
}
}
// Init 初始化 Redis 连接并 ping 验证。
func (m *RedisManager) Init(cfg *config.Config) error {
m.mu.Lock()
defer m.mu.Unlock()
client := redis.NewClient(&redis.Options{
Addr: cfg.Redis.Addr(),
Password: cfg.Redis.Password,
DB: cfg.Redis.DB,
})
ctx := context.Background()
if err := client.Ping(ctx).Err(); err != nil {
client.Close()
return fmt.Errorf("Redis 连接失败: %w", err)
}
m.cfg = cfg
m.client = client
RedisClient = client // 同步兼容 facade
logger.Info("Redis 连接成功", zap.String("addr", cfg.Redis.Addr()))
return nil
}
// Close 关闭 Redis 连接。
func (m *RedisManager) Close() error {
m.mu.Lock()
defer m.mu.Unlock()
if m.client == nil {
return nil
}
err := m.client.Close()
m.client = nil
RedisClient = nil
return err
}
// Client 返回当前 Redis 客户端(未初始化返回 nil)。
func (m *RedisManager) Client() *redis.Client {
m.mu.Lock()
defer m.mu.Unlock()
return m.client
}
// HealthCheck Redis 健康检查。
func (m *RedisManager) HealthCheck(ctx context.Context) error {
m.mu.Lock()
client := m.client
m.mu.Unlock()
if client == nil {
return fmt.Errorf("Redis 未初始化")
}
return client.Ping(ctx).Err()
}
// --- 包级 facade(代理到 DefaultRedis,兼容存量) ---
// InitRedis 初始化 Redis 连接
func InitRedis(cfg *config.Config) error {
return DefaultRedis.Init(cfg)
}
// CloseRedis 关闭 Redis 连接
func CloseRedis() error {
return DefaultRedis.Close()
}
// HealthCheckRedis Redis 健康检查
func HealthCheckRedis(ctx context.Context) error {
return DefaultRedis.HealthCheck(ctx)
}
// GetRedis 获取 Redis 客户端
func GetRedis() *redis.Client {
return DefaultRedis.Client()
}