| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 | package redisimport (	"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 TTLfunc 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 CacheStoreRedistype 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}
 |