redis/config.go

140 lines
3.1 KiB
Go
Raw Permalink Normal View History

package redis
import (
"fmt"
"net/url"
"strconv"
"sync"
"time"
"apigo.cc/go/cast"
"apigo.cc/go/crypto"
"apigo.cc/go/log"
"apigo.cc/go/safe"
)
type Config struct {
Host string
Password string
DB int
MaxActive int
MaxIdle int
IdleTimeout time.Duration
ConnectTimeout time.Duration
ReadTimeout time.Duration
WriteTimeout time.Duration
LogSlow time.Duration
logger *log.Logger
pwd *safe.SafeBuf
}
var redisConfigs = make(map[string]*Config)
var redisConfigsLock = sync.RWMutex{}
var confAes, _ = crypto.NewAESGCMAndEraseKey([]byte("?GQ$0K0GgLdO=f+~L68PLm$uhKr4'=tV"), []byte("VFs7@sK61cj^f?HZ"))
var keysOnce = sync.Once{}
func SetEncryptKeys(key, iv []byte) {
keysOnce.Do(func() {
confAes.Close()
confAes, _ = crypto.NewAESGCMAndEraseKey(key, iv)
})
}
func (conf *Config) ConfigureBy(setting string) {
redisConfigsLock.Lock()
redisConfigs[setting] = conf
redisConfigsLock.Unlock()
urlInfo, err := url.Parse(setting)
if err != nil {
conf.logger.Error(err.Error(), "url", setting)
return
}
if urlInfo.Scheme != "redis" {
conf.logger.Error("unsupported scheme", "url", setting)
return
}
conf.Host = urlInfo.Host
dbStr := urlInfo.Query().Get("database")
if dbStr == "" && len(urlInfo.Path) > 1 {
dbStr = urlInfo.Path[1:]
}
if len(dbStr) > 0 {
db, err := strconv.Atoi(dbStr)
if err != nil {
conf.logger.Error(err.Error(), "url", setting)
}
if err == nil && db >= 0 && db <= 15 {
conf.DB = db
}
}
conf.Password, _ = urlInfo.User.Password()
conf.LogSlow = cast.Duration(urlInfo.Query().Get("logSlow"))
conf.MaxIdle = cast.Int(urlInfo.Query().Get("maxIdle"))
conf.MaxActive = cast.Int(urlInfo.Query().Get("maxActive"))
conf.ConnectTimeout = cast.Duration(urlInfo.Query().Get("connectTimeout"))
conf.ReadTimeout = cast.Duration(urlInfo.Query().Get("readTimeout"))
conf.WriteTimeout = cast.Duration(urlInfo.Query().Get("writeTimeout"))
conf.IdleTimeout = cast.Duration(urlInfo.Query().Get("idleTimeout"))
}
func (conf *Config) Dsn() string {
return fmt.Sprintf("redis://:****@%s/%d?timeout=%s&logSlow=%s", conf.Host, conf.DB, conf.ConnectTimeout, conf.LogSlow)
}
func parseByName(name string) *Config {
// config name support Host:Port
args := cast.Split(name, ":")
db := 0
if len(args) > 1 {
arg1, err := strconv.Atoi(args[1])
if err == nil && arg1 >= 0 && arg1 <= 15 {
name = args[0]
db = arg1
}
}
redisConfigsLock.RLock()
conf := redisConfigs[name]
redisConfigsLock.RUnlock()
if conf == nil {
conf = new(Config)
redisConfigsLock.Lock()
redisConfigs[name] = conf
redisConfigsLock.Unlock()
if len(args) > 1 {
arg1, err := strconv.Atoi(args[1])
if err == nil && arg1 >= 0 && arg1 <= 15 {
conf.DB = arg1
} else {
conf.Host = args[0] + ":" + args[1]
}
}
}
for i := 2; i < len(args); i++ {
arg2, err := strconv.Atoi(args[i])
if err == nil {
if arg2 >= 0 && arg2 <= 15 {
conf.DB = arg2
} else {
conf.Password = args[i]
}
} else {
conf.Password = args[i]
}
}
if conf.DB == 0 && db > 0 && db <= 15 {
conf.DB = db
}
return conf
}