mirror of
https://github.com/go-eagle/eagle.git
synced 2025-09-28 05:12:14 +08:00
132 lines
2.6 KiB
Go
132 lines
2.6 KiB
Go
package redis
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/alicebob/miniredis/v2"
|
|
"github.com/redis/go-redis/extra/redisotel/v9"
|
|
"github.com/redis/go-redis/v9"
|
|
|
|
"github.com/go-eagle/eagle/pkg/config"
|
|
)
|
|
|
|
// RedisClient redis 客户端
|
|
var RedisClient *redis.Client
|
|
|
|
const (
|
|
// ErrRedisNotFound not exist in redis
|
|
ErrRedisNotFound = redis.Nil
|
|
// DefaultRedisName default redis name
|
|
DefaultRedisName = "default"
|
|
)
|
|
|
|
// RedisManager define a redis manager
|
|
// nolint
|
|
type RedisManager struct {
|
|
clients map[string]*redis.Client
|
|
*sync.RWMutex
|
|
}
|
|
|
|
// Init init a default redis instance
|
|
func Init() (*redis.Client, func(), error) {
|
|
clientManager := NewRedisManager()
|
|
rdb, err := clientManager.GetClient(DefaultRedisName)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("init redis err: %s", err.Error())
|
|
}
|
|
cleanFunc := func() {
|
|
_ = rdb.Close()
|
|
}
|
|
RedisClient = rdb
|
|
|
|
return rdb, cleanFunc, nil
|
|
}
|
|
|
|
// NewRedisManager create a redis manager
|
|
func NewRedisManager() *RedisManager {
|
|
return &RedisManager{
|
|
clients: make(map[string]*redis.Client),
|
|
RWMutex: &sync.RWMutex{},
|
|
}
|
|
}
|
|
|
|
// GetClient get a redis instance
|
|
func (r *RedisManager) GetClient(name string) (*redis.Client, error) {
|
|
// get client from map
|
|
r.RLock()
|
|
if client, ok := r.clients[name]; ok {
|
|
r.RUnlock()
|
|
return client, nil
|
|
}
|
|
r.RUnlock()
|
|
|
|
c, err := LoadConf(name)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("load redis conf err: %v", err))
|
|
}
|
|
|
|
// create a redis client
|
|
r.Lock()
|
|
defer r.Unlock()
|
|
rdb := redis.NewClient(&redis.Options{
|
|
Addr: c.Addr,
|
|
Password: c.Password,
|
|
DB: c.DB,
|
|
MinIdleConns: c.MinIdleConn,
|
|
DialTimeout: c.DialTimeout,
|
|
ReadTimeout: c.ReadTimeout,
|
|
WriteTimeout: c.WriteTimeout,
|
|
PoolSize: c.PoolSize,
|
|
PoolTimeout: c.PoolTimeout,
|
|
})
|
|
|
|
// check redis if is ok
|
|
_, err = rdb.Ping(context.Background()).Result()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// hook tracing (using open telemetry)
|
|
if c.EnableTrace {
|
|
if err := redisotel.InstrumentTracing(rdb); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
r.clients[name] = rdb
|
|
|
|
return rdb, nil
|
|
}
|
|
|
|
// LoadConf load redis config
|
|
func LoadConf(name string) (ret *Config, err error) {
|
|
v, err := config.LoadWithType("redis", "yaml")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var c Config
|
|
err = v.UnmarshalKey(name, &c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &c, nil
|
|
}
|
|
|
|
// InitTestRedis 实例化一个可以用于单元测试的redis
|
|
func InitTestRedis() {
|
|
mr, err := miniredis.Run()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
// 打开下面命令可以测试链接关闭的情况
|
|
// defer mr.Close()
|
|
|
|
RedisClient = redis.NewClient(&redis.Options{
|
|
Addr: mr.Addr(),
|
|
})
|
|
fmt.Println("mini redis addr:", mr.Addr())
|
|
}
|