feat(cache):实验性增加缓存操作函数。

This commit is contained in:
徐涛 2022-08-25 09:48:21 +08:00
parent 4aa7221158
commit 4025965e98
7 changed files with 256 additions and 1 deletions

8
cache/abstract.go vendored
View File

@ -10,6 +10,14 @@ import (
"github.com/vmihailenco/msgpack/v5"
)
const (
TAG_ENTITY = "ENTITY"
TAG_COUNT = "COUNT"
TAG_SEARCH = "SEARCH"
TAG_EXISTS = "CHECK"
TAG_SESSION = "SESSION"
)
// 向Redis缓存中保存一个数据
// ! 如果需要长期保存一个数据那么需要向expires传入0。
func Cache[T interface{}](key string, value *T, expires time.Duration) error {

52
cache/count.go vendored Normal file
View File

@ -0,0 +1,52 @@
package cache
import (
"electricity_bill_calc/global"
"fmt"
"strconv"
"strings"
)
func assembleCountKey(entityName string) string {
var keys = make([]string, 0)
keys = append(keys, strings.ToUpper(entityName))
return CacheKey(TAG_COUNT, keys...)
}
func assembleCountIdentification(additional ...string) string {
var b strings.Builder
for _, s := range additional {
fmt.Fprintf(&b, ":%s", s)
}
return b.String()
}
// 向缓存中缓存模型名称明确的包含指定条件的实体记录数量
func CacheCount(entityName string, count int64, conditions ...string) error {
countKey := assembleCountKey(entityName)
identification := assembleCountIdentification(conditions...)
result := global.RedisConn.HSet(global.Ctx, countKey, map[string]interface{}{identification: count})
return result.Err()
}
// 从缓存中获取模型名称明确的,包含指定条件的实体记录数量
func RetreiveCount(entityName string, condtions ...string) (int64, error) {
countKey := assembleCountKey(entityName)
identification := assembleCountIdentification(condtions...)
result := global.RedisConn.HGet(global.Ctx, countKey, identification)
if result.Err() != nil {
return -1, result.Err()
}
count, err := strconv.ParseInt(result.Val(), 10, 64)
if err != nil {
return -1, err
}
return count, nil
}
// 删除指定模型名称的数量缓存
func AbolishCountEntity(entityName string) error {
countKey := assembleCountKey(entityName)
result := global.RedisConn.Del(global.Ctx, countKey)
return result.Err()
}

61
cache/entity.go vendored Normal file
View File

@ -0,0 +1,61 @@
package cache
import (
"electricity_bill_calc/global"
"fmt"
"strings"
)
func assembleEntityKey(entityName, id string) string {
var keys = make([]string, 0)
keys = append(keys, TAG_ENTITY)
keys = append(keys, strings.ToUpper(entityName), id)
var b strings.Builder
for _, s := range keys {
fmt.Fprintf(&b, ":%s", s)
}
return b.String()
}
// 缓存模型名称明确的使用ID进行检索的实体内容。
func CacheEntity[T any](instance T, entityName, id string) error {
entityKey := assembleEntityKey(entityName, id)
err := Cache(entityKey, &instance, 0)
return err
}
// 从缓存中取出模型名称明确的使用ID进行检索的实体内容。
func RetreiveEntity[T any](entityName, id string) (T, error) {
entityKey := assembleEntityKey(entityName, id)
instance, err := Retreive[T](entityKey)
return *instance, err
}
// 精确的从缓存中删除指定模型名称、指定ID的实体内容。
func AbolishSpecificEntity(entityName, id string) (bool, error) {
entityKey := assembleEntityKey(entityName, id)
return Delete(entityKey)
}
// 从缓存中删除指定模型名称的所有内容。
func AbolishEntity(entityName string) error {
var (
cursor uint64
keys = make([]string, 0)
)
pattern := fmt.Sprintf("%s:%s:*", TAG_ENTITY, strings.ToUpper(entityName))
for {
k, cursor, err := global.RedisConn.Scan(global.Ctx, cursor, pattern, 20).Result()
if err != nil {
return err
}
keys = append(keys, k...)
if cursor == 0 {
break
}
}
pipeline := global.RedisConn.Pipeline()
pipeline.Del(global.Ctx, keys...)
_, err := pipeline.Exec(global.Ctx)
return err
}

70
cache/exists.go vendored Normal file
View File

@ -0,0 +1,70 @@
package cache
import (
"electricity_bill_calc/global"
"electricity_bill_calc/tools"
"fmt"
"strings"
)
func assembleExistsKey(entityName string) string {
var keys = make([]string, 0)
keys = append(keys, strings.ToUpper(entityName))
return CacheKey(TAG_EXISTS, keys...)
}
func assembleExistsIdentification(id string, additional ...string) string {
var b strings.Builder
b.WriteString(id)
for _, s := range additional {
fmt.Fprintf(&b, ":%s", s)
}
return b.String()
}
// 缓存模型名称明确的、包含指定ID以及一些附加条件的记录
func CacheExists(entityName, id string, conditions ...string) error {
existskey := assembleExistsKey(entityName)
identification := assembleExistsIdentification(id, conditions...)
result := global.RedisConn.SAdd(global.Ctx, existskey, identification)
return result.Err()
}
// 从缓存中获取模型名称明确、包含指定ID以及一些附加条件的实体是否存在的标记函数在返回false时不保证数据库中相关记录也不存在
func CheckExists(entityName, id string, condtions ...string) (bool, error) {
existsKey := assembleExistsKey(entityName)
identification := assembleExistsIdentification(id, condtions...)
result := global.RedisConn.SIsMember(global.Ctx, existsKey, identification)
return result.Val(), result.Err()
}
// 从缓存中删除模型名称明确、包含指定ID的全部实体存在标记
func AbolishExists(entityName, id string) error {
existsKey := assembleExistsKey(entityName)
pattern := fmt.Sprintf("%s*", id)
var (
cursor uint64
elems = make([]string, 0)
)
for {
k, cursor, err := global.RedisConn.SScan(global.Ctx, existsKey, cursor, pattern, 20).Result()
if err != nil {
return err
}
elems = append(elems, k...)
if cursor == 0 {
break
}
}
pipeline := global.RedisConn.Pipeline()
pipeline.SRem(global.Ctx, existsKey, tools.ConvertSliceToInterfaceSlice(elems)...)
_, err := pipeline.Exec(global.Ctx)
return err
}
// 从缓存中删除指定模型名称的全部存在标记
func AbolishExistsEntity(entityName string) error {
existskey := assembleExistsKey(entityName)
result := global.RedisConn.Del(global.Ctx, existskey)
return result.Err()
}

56
cache/search.go vendored Normal file
View File

@ -0,0 +1,56 @@
package cache
import (
"electricity_bill_calc/global"
"fmt"
"strings"
)
func assembleSearchKey(entityName string, additional ...string) string {
var keys = make([]string, 0)
keys = append(keys, TAG_SEARCH)
keys = append(keys, strings.ToUpper(entityName))
keys = append(keys, additional...)
var b strings.Builder
for _, s := range keys {
fmt.Fprintf(&b, ":%s", s)
}
return b.String()
}
// 缓存模型名称明确的使用或者包含非ID检索条件的实体内容。
func CacheSearch[T any](instance T, entityName string, conditions ...string) error {
searchKey := assembleSearchKey(entityName, conditions...)
err := Cache(searchKey, &instance, 0)
return err
}
// 从缓存中取得模型名称明确的使用或者包含非ID检索条件的实体内容。
func RetreiveSearch[T any](entityName string, conditions ...string) (T, error) {
searchKey := assembleSearchKey(entityName, conditions...)
instance, err := Retreive[T](searchKey)
return *instance, err
}
// 从缓存中删除全部指定模型名称的实体内容。
func AbolishSearch(entityName string) error {
var (
cursor uint64
keys = make([]string, 0)
)
pattern := fmt.Sprintf("%s:%s:*", TAG_SEARCH, strings.ToUpper(entityName))
for {
k, cursor, err := global.RedisConn.Scan(global.Ctx, cursor, pattern, 20).Result()
if err != nil {
return err
}
keys = append(keys, k...)
if cursor == 0 {
break
}
}
pipeline := global.RedisConn.Pipeline()
pipeline.Del(global.Ctx, keys...)
_, err := pipeline.Exec(global.Ctx)
return err
}

2
cache/session.go vendored
View File

@ -9,7 +9,7 @@ import (
func SessionKey(keys ...string) string {
var b strings.Builder
b.WriteString("session")
b.WriteString(TAG_SESSION)
for _, s := range keys {
fmt.Fprintf(&b, ":%s", s)
}

View File

@ -30,3 +30,11 @@ func ConvertStructToMap[T any](origin T) map[string]interface{} {
json.Unmarshal(incr, &dest)
return dest
}
func ConvertSliceToInterfaceSlice[T any](origin []T) []interface{} {
dest := make([]interface{}, len(origin))
for i, e := range origin {
dest[i] = e
}
return dest
}