301 lines
9.1 KiB
Go
301 lines
9.1 KiB
Go
package dao
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/gomodule/redigo/redis"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
const (
|
|
MidFmt = "%s:%v" // {appId}:{uid}
|
|
_prefixMidServer = "mid_%s:%v" // mid_{appId}:{uid} -> key:server
|
|
_prefixKeyServer = "key_%s" // key_{key} -> server
|
|
_prefixKeyUser = "usr_%s" // usr_{key} -> {appId}:{uid}
|
|
_prefixGroupServer = "group_%s:%s" // group_{appId}:{gid} -> {server}:{score}
|
|
)
|
|
|
|
func keyMidServer(appId string, mid string) string {
|
|
return fmt.Sprintf(_prefixMidServer, appId, mid)
|
|
}
|
|
|
|
func keyKeyServer(key string) string {
|
|
return fmt.Sprintf(_prefixKeyServer, key)
|
|
}
|
|
|
|
func keyKeyUser(key string) string {
|
|
return fmt.Sprintf(_prefixKeyUser, key)
|
|
}
|
|
|
|
func keyGroupServer(appId, gid string) string {
|
|
return fmt.Sprintf(_prefixGroupServer, appId, gid)
|
|
}
|
|
|
|
func (d *Dao) pingRedis(c context.Context) (err error) {
|
|
conn := d.redis.Get()
|
|
_, err = conn.Do("SET", "PING", "PONG")
|
|
conn.Close()
|
|
return
|
|
}
|
|
|
|
func (d *Dao) GetMember(c context.Context, key string) (appId string, mid string, err error) {
|
|
conn := d.redis.Get()
|
|
defer conn.Close()
|
|
ss, err := redis.String(conn.Do("GET", keyKeyUser(key)))
|
|
if err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.DO(GET)")
|
|
return "", "", err
|
|
}
|
|
arr := strings.Split(ss, ":")
|
|
if len(arr) != 2 {
|
|
return "", "", errors.New("invalid key")
|
|
}
|
|
appId = arr[0]
|
|
mid = arr[1]
|
|
return
|
|
}
|
|
|
|
func (d *Dao) GetServer(c context.Context, key string) (server string, err error) {
|
|
conn := d.redis.Get()
|
|
defer conn.Close()
|
|
if server, err = redis.String(conn.Do("GET", keyKeyServer(key))); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.DO(GET)")
|
|
}
|
|
return
|
|
}
|
|
|
|
func (d *Dao) AddMapping(c context.Context, mid string, appId string, key string, server string) (err error) {
|
|
conn := d.redis.Get()
|
|
defer conn.Close()
|
|
var n = 4
|
|
if mid != "" {
|
|
if err = conn.Send("HSET", keyMidServer(appId, mid), key, server); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(HSET %s,%s,%s,%s) error", appId, mid, server, key))
|
|
return
|
|
}
|
|
if err = conn.Send("EXPIRE", keyMidServer(appId, mid), d.redisExpire); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(EXPIRE %s,%s,%s,%s)", appId, mid, key, server))
|
|
return
|
|
}
|
|
n += 2
|
|
}
|
|
if err = conn.Send("SET", keyKeyServer(key), server); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(HSET %s,%s,%s) error", mid, server, key))
|
|
return
|
|
}
|
|
if err = conn.Send("EXPIRE", keyKeyServer(key), d.redisExpire); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(EXPIRE %s,%s,%s) error", mid, key, server))
|
|
return
|
|
}
|
|
user := fmt.Sprintf(MidFmt, appId, mid)
|
|
if err = conn.Send("SET", keyKeyUser(key), user); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(HSET %s,%s,%s) error", mid, appId, key))
|
|
return
|
|
}
|
|
if err = conn.Send("EXPIRE", keyKeyUser(key), d.redisExpire); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(EXPIRE %s,%s,%s) error", mid, appId, key))
|
|
return
|
|
}
|
|
if err = conn.Flush(); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.Flush() error")
|
|
return
|
|
}
|
|
for i := 0; i < n; i++ {
|
|
if _, err = conn.Receive(); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.Receive() error")
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// ExpireMapping expire a mapping.
|
|
func (d *Dao) ExpireMapping(c context.Context, mid string, appId string, key string) (has bool, err error) {
|
|
conn := d.redis.Get()
|
|
defer conn.Close()
|
|
var n = 2
|
|
if mid != "" {
|
|
if err = conn.Send("EXPIRE", keyMidServer(appId, mid), d.redisExpire); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(EXPIRE %s) error", keyMidServer(appId, mid)))
|
|
return
|
|
}
|
|
n++
|
|
}
|
|
if err = conn.Send("EXPIRE", keyKeyServer(key), d.redisExpire); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(EXPIRE %s) error", keyKeyServer(key)))
|
|
return
|
|
}
|
|
if err = conn.Send("EXPIRE", keyKeyUser(key), d.redisExpire); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(EXPIRE %s) error", keyKeyServer(key)))
|
|
return
|
|
}
|
|
if err = conn.Flush(); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.Flush() error")
|
|
return
|
|
}
|
|
for i := 0; i < n; i++ {
|
|
if has, err = redis.Bool(conn.Receive()); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.Receive() error")
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (d *Dao) DelMapping(c context.Context, mid string, appId string, key string) (has bool, err error) {
|
|
conn := d.redis.Get()
|
|
defer conn.Close()
|
|
var n = 2
|
|
if mid != "" {
|
|
if err = conn.Send("HDEL", keyMidServer(appId, mid), key); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(HDEL %s) error", keyMidServer(appId, mid)))
|
|
return
|
|
}
|
|
n++
|
|
}
|
|
if err = conn.Send("DEL", keyKeyServer(key)); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(DEL %s) error", keyKeyServer(key)))
|
|
return
|
|
}
|
|
if err = conn.Send("DEL", keyKeyUser(key)); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(DEL %s) error", keyKeyUser(key)))
|
|
return
|
|
}
|
|
if err = conn.Flush(); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.Flush() error")
|
|
return
|
|
}
|
|
for i := 0; i < n; i++ {
|
|
if has, err = redis.Bool(conn.Receive()); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.Receive() error")
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// ServersByKeys get a server by key.
|
|
func (d *Dao) ServersByKeys(c context.Context, keys []string) (res []string, err error) {
|
|
conn := d.redis.Get()
|
|
defer conn.Close()
|
|
var args []interface{}
|
|
for _, key := range keys {
|
|
args = append(args, keyKeyServer(key))
|
|
}
|
|
if res, err = redis.Strings(conn.Do("MGET", args...)); err != nil {
|
|
log.Error().Err(err).Msg(fmt.Sprintf("conn.Do(MGET %v) error", args))
|
|
}
|
|
return
|
|
}
|
|
|
|
// KeysByMids get a key server by mid.
|
|
func (d *Dao) KeysByMids(c context.Context, appId string, mids []string) (ress map[string]string, olMids []string, err error) {
|
|
conn := d.redis.Get()
|
|
defer conn.Close()
|
|
ress = make(map[string]string)
|
|
for _, mid := range mids {
|
|
if err = conn.Send("HGETALL", keyMidServer(appId, mid)); err != nil {
|
|
log.Error().Err(err).Msg(fmt.Sprintf("conn.Do(HGETALL %s) error", mid))
|
|
return
|
|
}
|
|
}
|
|
if err = conn.Flush(); err != nil {
|
|
log.Error().Err(err).Msg("conn.Flush() error")
|
|
return
|
|
}
|
|
for idx := 0; idx < len(mids); idx++ {
|
|
var (
|
|
res map[string]string
|
|
)
|
|
if res, err = redis.StringMap(conn.Receive()); err != nil {
|
|
log.Error().Err(err).Msg("conn.Receive() error")
|
|
return
|
|
}
|
|
if len(res) > 0 {
|
|
olMids = append(olMids, mids[idx])
|
|
}
|
|
for k, v := range res {
|
|
ress[k] = v
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
//groups
|
|
func (d *Dao) IncGroupServer(c context.Context, appId, key, server string, gid []string) (err error) {
|
|
conn := d.redis.Get()
|
|
defer conn.Close()
|
|
var n = 0
|
|
for _, g := range gid {
|
|
if err = conn.Send("ZINCRBY", keyGroupServer(appId, g), "1", server); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(
|
|
fmt.Sprintf("conn.Send(ZINCRBY %s,%s,%s) error", keyGroupServer(appId, g), "1", server))
|
|
return
|
|
}
|
|
//if err = conn.Send("EXPIRE", keyGroupServer(appId, g), d.redisExpire); err != nil {
|
|
// log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(EXPIRE %s,%s,%s,%s)", appId, mid, key, server))
|
|
// return
|
|
//}
|
|
n++
|
|
}
|
|
if err = conn.Flush(); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.Flush() error")
|
|
return
|
|
}
|
|
for i := 0; i < n; i++ {
|
|
if _, err = conn.Receive(); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.Receive() error")
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (d *Dao) DecGroupServer(c context.Context, appId, key, server string, gid []string) (err error) {
|
|
conn := d.redis.Get()
|
|
defer conn.Close()
|
|
var n = 0
|
|
for _, g := range gid {
|
|
if err = conn.Send("ZINCRBY", keyGroupServer(appId, g), "-1", server); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg(
|
|
fmt.Sprintf("conn.Send(ZINCRBY %s,%s,%s) error", keyGroupServer(appId, g), "-1", server))
|
|
return
|
|
}
|
|
//if err = conn.Send("EXPIRE", keyGroupServer(appId, g), d.redisExpire); err != nil {
|
|
// log.Error().Str("key", key).Err(err).Msg(fmt.Sprintf("conn.Send(EXPIRE %s,%s,%s,%s)", appId, mid, key, server))
|
|
// return
|
|
//}
|
|
n++
|
|
}
|
|
if err = conn.Flush(); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.Flush() error")
|
|
return
|
|
}
|
|
for i := 0; i < n; i++ {
|
|
if _, err = conn.Receive(); err != nil {
|
|
log.Error().Str("key", key).Err(err).Msg("conn.Receive() error")
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// KeysByMids get a key server by mid.
|
|
func (d *Dao) ServersByGid(c context.Context, appId string, gid string) (res []string, err error) {
|
|
conn := d.redis.Get()
|
|
defer conn.Close()
|
|
res = make([]string, 0)
|
|
ress := make(map[string]string)
|
|
if ress, err = redis.StringMap(conn.Do("ZRANGE", keyGroupServer(appId, gid), "0", "-1", "WITHSCORES")); err != nil {
|
|
log.Error().Str("appId", appId).Str("gid", gid).Err(err).Msg(
|
|
fmt.Sprintf("conn.DO(ZRANGE %s,%s,%s,%s) error", keyGroupServer(appId, gid), "0", "-1", "WITHSCORES"))
|
|
}
|
|
for k, _ := range ress {
|
|
res = append(res, k)
|
|
}
|
|
return
|
|
}
|