Files
chain33-im/logic/dao/redis.go
2022-03-17 15:55:27 +08:00

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
}