140 lines
3.1 KiB
Go
140 lines
3.1 KiB
Go
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
|
|
}
|