electricity_bill_calc_service/cache/relation.go

123 lines
3.3 KiB
Go

package cache
import (
"electricity_bill_calc/global"
"fmt"
"strings"
"github.com/rueian/rueidis"
"github.com/samber/lo"
)
const (
STORE_TYPE_KEY = "KEY"
STORE_TYPE_SET = "SET"
STORE_TYPE_HASH = "HASH"
)
func assembleRelationKey(relationName string) string {
var keys = make([]string, 0)
keys = append(keys, strings.ToUpper(relationName))
return CacheKey(TAG_RELATION, keys...)
}
func assembleRelationIdentity(storeType, key string, field ...string) string {
var identity = make([]string, 0)
identity = append(identity, storeType, key)
identity = append(identity, field...)
return strings.Join(identity, ";")
}
// 向缓存中保存与指定关联名称相关联的键的名称以及键的类型和子字段的组成。
func CacheRelation(relationName, storeType, key string, field ...string) error {
relationKey := assembleRelationKey(relationName)
relationIdentity := assembleRelationIdentity(storeType, key, field...)
cmd := global.RedisConn.B().Sadd().Key(relationKey).Member(relationIdentity).Build()
result := global.RedisConn.Do(global.Ctx, cmd)
return result.Error()
}
// 从缓存中清理指定的关联键
func AbolishRelation(relationName string) error {
relationKey := assembleRelationKey(relationName)
cmd := global.RedisConn.B().Smembers().Key(relationKey).Build()
relationItems, err := global.RedisConn.Do(global.Ctx, cmd).AsStrSlice()
if err != nil {
return err
}
var cmds = make(rueidis.Commands, 0)
for _, item := range relationItems {
separated := strings.Split(item, ";")
switch separated[0] {
case STORE_TYPE_KEY:
cmd := global.RedisConn.B().Del().Key(separated[1]).Build()
cmds = append(cmds, cmd)
case STORE_TYPE_HASH:
cmd := global.RedisConn.B().Hdel().Key(separated[1]).Field(separated[2:]...).Build()
cmds = append(cmds, cmd)
case STORE_TYPE_SET:
cmd := global.RedisConn.B().Srem().Key(separated[1]).Member(separated[2:]...).Build()
cmds = append(cmds, cmd)
}
}
errs := global.RedisConn.DoMulti(global.Ctx, cmds...)
firstErr, has := lo.Find(errs, func(elem rueidis.RedisResult) bool {
return elem.Error() != nil
})
if has {
return firstErr.Error()
} else {
return nil
}
}
func ClearOrphanRelationItems() error {
var (
err error
cursor int64
keys = make([]string, 0)
sKeys []string
)
for {
scanCmd := global.RedisConn.B().Scan().Cursor(cursor).Match(fmt.Sprintf("%s:*", TAG_RELATION)).Count(20).Build()
results := global.RedisConn.Do(global.Ctx, scanCmd)
cursor, sKeys, err = dissembleScan(results)
if err != nil {
return err
}
keys = append(keys, sKeys...)
if cursor == 0 {
break
}
}
var cmds = make(rueidis.Commands, 0)
for _, key := range keys {
relationItemsCmd := global.RedisConn.B().Smembers().Key(key).Build()
results := global.RedisConn.Do(global.Ctx, relationItemsCmd)
relationItems, err := results.AsStrSlice()
if err != nil {
return err
}
for _, item := range relationItems {
separated := strings.Split(item, ";")
exist, err := Exists(separated[1])
if err != nil {
return err
}
if !exist {
cmd := global.RedisConn.B().Srem().Key(key).Member(item).Build()
cmds = append(cmds, cmd)
}
}
}
errs := global.RedisConn.DoMulti(global.Ctx, cmds...)
firstErr, has := lo.Find(errs, func(elem rueidis.RedisResult) bool {
return elem.Error() != nil
})
if has {
return firstErr.Error()
} else {
return nil
}
}