feat(app): 提供通用缓存
This commit is contained in:
122
pkg/cache/common/common.go
vendored
Normal file
122
pkg/cache/common/common.go
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"gitea.ddegame.cn/open/servicebase/pkg/cache"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
type DBCacheFetcher[T any] func(fieldKey string) (*T, error)
|
||||
type DBCacheFetcherMany[T any] func(fieldKeys []string) (map[string]*T, error)
|
||||
|
||||
func GetOrCacheOne[T any](cli *redis.Client, hashKey string, fieldKey string, dbFetcher DBCacheFetcher[T]) (*T, error) {
|
||||
if len(fieldKey) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var cachedStr string
|
||||
var err error
|
||||
if cachedStr, err = cli.HGet(cache.Ctx(), hashKey, fieldKey).Result(); err != nil && !errors.Is(err, redis.Nil) {
|
||||
return nil, err
|
||||
}
|
||||
var model *T
|
||||
if len(cachedStr) > 0 {
|
||||
model = new(T)
|
||||
if err = json.Unmarshal([]byte(cachedStr), model); err == nil {
|
||||
return model, nil
|
||||
}
|
||||
}
|
||||
if model, err = dbFetcher(fieldKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if model == nil {
|
||||
return nil, nil
|
||||
}
|
||||
bytes, marshalErr := json.Marshal(model)
|
||||
if marshalErr != nil {
|
||||
return model, nil
|
||||
}
|
||||
_, _ = cli.HSet(cache.Ctx(), hashKey, fieldKey, string(bytes)).Result()
|
||||
return model, nil
|
||||
}
|
||||
|
||||
func GetOrCacheMany[T any](cli *redis.Client, hashKey string, fieldKeyList []string, dbFetcherMany DBCacheFetcherMany[T]) ([]*T, error) {
|
||||
if len(fieldKeyList) == 0 {
|
||||
return make([]*T, 0), nil
|
||||
}
|
||||
finalResults := make([]*T, len(fieldKeyList))
|
||||
missingKeysMap := make(map[string]int)
|
||||
missingKeysList := make([]string, 0)
|
||||
values, err := cli.HMGet(cache.Ctx(), hashKey, fieldKeyList...).Result()
|
||||
if err != nil && !errors.Is(err, redis.Nil) {
|
||||
return nil, err
|
||||
}
|
||||
for i, fieldKey := range fieldKeyList {
|
||||
value := values[i]
|
||||
if value == nil {
|
||||
missingKeysMap[fieldKey] = i
|
||||
missingKeysList = append(missingKeysList, fieldKey)
|
||||
continue
|
||||
}
|
||||
cachedStr, ok := value.(string)
|
||||
if !ok {
|
||||
missingKeysMap[fieldKey] = i
|
||||
missingKeysList = append(missingKeysList, fieldKey)
|
||||
continue
|
||||
}
|
||||
model := new(T)
|
||||
if jsonErr := json.Unmarshal([]byte(cachedStr), model); jsonErr == nil {
|
||||
finalResults[i] = model
|
||||
} else {
|
||||
missingKeysMap[fieldKey] = i
|
||||
missingKeysList = append(missingKeysList, fieldKey)
|
||||
}
|
||||
}
|
||||
if len(missingKeysList) == 0 {
|
||||
return finalResults, nil
|
||||
}
|
||||
dbModelsMap, err := dbFetcherMany(missingKeysList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cacheMap := make(map[string]any)
|
||||
for fieldKey, model := range dbModelsMap {
|
||||
originalIndex, found := missingKeysMap[fieldKey]
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
finalResults[originalIndex] = model
|
||||
if model != nil {
|
||||
if bytes, marshalErr := json.Marshal(model); marshalErr == nil {
|
||||
cacheMap[fieldKey] = string(bytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(cacheMap) > 0 {
|
||||
_, _ = cli.HSet(cache.Ctx(), hashKey, cacheMap).Result()
|
||||
}
|
||||
return finalResults, nil
|
||||
}
|
||||
|
||||
func DelCacheFields(cli *redis.Client, hashKey string, fieldKeyList ...string) error {
|
||||
if len(fieldKeyList) == 0 {
|
||||
return nil
|
||||
}
|
||||
_, err := cli.HDel(cache.Ctx(), hashKey, fieldKeyList...).Result()
|
||||
if err != nil && !errors.Is(err, redis.Nil) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DelCacheHash(cli *redis.Client, hashKey string) error {
|
||||
if len(hashKey) == 0 {
|
||||
return nil
|
||||
}
|
||||
_, err := cli.Del(cache.Ctx(), hashKey).Result()
|
||||
if err != nil && !errors.Is(err, redis.Nil) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user