123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- package redis
- import (
- "context"
- "fmt"
- "kpt-pasture/config"
- "math/rand"
- "time"
- "gitee.com/xuyiping_admin/pkg/xerr"
- "github.com/eko/gocache/cache"
- "github.com/eko/gocache/marshaler"
- "github.com/eko/gocache/metrics"
- "github.com/eko/gocache/store"
- redisv7 "github.com/go-redis/redis/v7"
- )
- func init() {
- rand.Seed(time.Now().UnixNano())
- }
- // Options redis 使用约束
- type Options = store.Options
- // TTL redis key TTL
- func TTL(duration time.Duration) *Options {
- return &store.Options{
- // 避免集中过期
- Expiration: duration + time.Duration(rand.Int31n(100))*time.Second,
- }
- }
- // CacheObject 缓存对象
- type CacheObject interface {
- CacheKey() string
- }
- // CacheStoreRedis Redis 缓存实例
- //
- //go:generate mockgen -destination mock/redismock.go -package redismock kpt_event/service/redis CacheStoreRedis
- type CacheStoreRedis interface {
- Namespace() string
- SetNamespace(string)
- // FullKey 返回带命名空间的完整key
- FullKey(key string) string
- Client() *redisv7.Client
- Get(ctx context.Context, Obj CacheObject) (interface{}, error)
- BatchGet(ctx context.Context, objects []CacheObject) (map[string]interface{}, error)
- Set(ctx context.Context, Obj CacheObject, options *store.Options) error
- TTL(ctx context.Context, obj CacheObject) (time.Duration, error)
- Delete(ctx context.Context, keys ...interface{}) error
- }
- func NewCacheStoreRedis(cfg *config.AppConfig) CacheStoreRedis {
- return NewCacheStoreRedisEntry(cfg)
- }
- func NewCacheStoreRedisEntry(cfg *config.AppConfig) *CacheStoreRedisEntry {
- client := NewClientLatest(cfg)
- redisStore := store.NewRedis(client, nil)
- promMetrics := metrics.NewPrometheus(cfg.Name())
- cacheManager := cache.NewMetric(promMetrics, cache.New(redisStore))
- marshal := marshaler.New(cacheManager)
- return &CacheStoreRedisEntry{
- client: client,
- cacheNamespace: config.Options().CacheNameSpace(),
- cacheMarshal: marshal,
- }
- }
- type CacheStoreRedisEntry struct {
- client *redisv7.Client
- cacheNamespace string
- cacheMarshal *marshaler.Marshaler
- }
- func (entry *CacheStoreRedisEntry) fullKey(key string) string {
- return fmt.Sprintf("%s:%s", entry.cacheNamespace, key)
- }
- func (entry *CacheStoreRedisEntry) FullKey(key string) string {
- return fmt.Sprintf("%s:%s", entry.cacheNamespace, key)
- }
- func (entry *CacheStoreRedisEntry) pureKey(key string) string {
- return key[len(entry.cacheNamespace):]
- }
- func (entry *CacheStoreRedisEntry) Namespace() string {
- return entry.cacheNamespace
- }
- func (entry *CacheStoreRedisEntry) SetNamespace(ns string) {
- entry.cacheNamespace = ns
- }
- func (entry *CacheStoreRedisEntry) Client() *redisv7.Client {
- return entry.client
- }
- func (entry *CacheStoreRedisEntry) BatchGet(ctx context.Context, objects []CacheObject) (map[string]interface{}, error) {
- result := make(map[string]interface{})
- for _, obj := range objects {
- got, err := entry.Get(ctx, obj)
- if err != nil {
- return nil, xerr.WithMessage(err, obj.CacheKey())
- }
- if got != nil {
- result[obj.CacheKey()] = got
- }
- }
- return result, nil
- }
- func (entry *CacheStoreRedisEntry) Get(ctx context.Context, obj CacheObject) (interface{}, error) {
- got, err := entry.cacheMarshal.Get(entry.fullKey(obj.CacheKey()), obj)
- if err != nil {
- if err == redisv7.Nil {
- return nil, nil
- }
- return nil, xerr.WithStack(err)
- }
- return got, nil
- }
- func (entry *CacheStoreRedisEntry) Set(ctx context.Context, obj CacheObject, options *store.Options) error {
- return entry.cacheMarshal.Set(entry.fullKey(obj.CacheKey()), obj, options)
- }
- func (entry *CacheStoreRedisEntry) TTL(ctx context.Context, obj CacheObject) (time.Duration, error) {
- return entry.client.TTL(entry.fullKey(obj.CacheKey())).Result()
- }
- func (entry *CacheStoreRedisEntry) Delete(ctx context.Context, keys ...interface{}) error {
- for _, key := range keys {
- switch keyItem := key.(type) {
- case string:
- if err := entry.cacheMarshal.Delete(entry.fullKey(keyItem)); err != nil {
- return xerr.WithStack(err)
- }
- case CacheObject:
- if err := entry.cacheMarshal.Delete(entry.fullKey(keyItem.CacheKey())); err != nil {
- return xerr.WithStack(err)
- }
- default:
- return xerr.New("invalid redis key type")
- }
- }
- return nil
- }
|