forked from free-lancers/electricity_bill_calc_service
		
	feat(cache):实验性增加缓存操作函数。
This commit is contained in:
		
							
								
								
									
										8
									
								
								cache/abstract.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								cache/abstract.go
									
									
									
									
										vendored
									
									
								
							| @@ -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
									
								
							
							
						
						
									
										52
									
								
								cache/count.go
									
									
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										61
									
								
								cache/entity.go
									
									
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										70
									
								
								cache/exists.go
									
									
									
									
										vendored
									
									
										Normal 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
									
								
							
							
						
						
									
										56
									
								
								cache/search.go
									
									
									
									
										vendored
									
									
										Normal 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
									
									
								
							
							
						
						
									
										2
									
								
								cache/session.go
									
									
									
									
										vendored
									
									
								
							| @@ -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) | ||||
| 	} | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user