github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/data/cache/store/redis.go (about) 1 package store 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/go-redis/redis/v7" 9 ) 10 11 // RedisClient global redis client 12 var RedisClient *redis.Client 13 14 const ( 15 // RedisType represents the storage type as a string value 16 RedisType = "redis" 17 // RedisTagPattern represents the tag pattern to be used as a key in specified storage 18 RedisTagPattern = "gocache_tag_%s" 19 ) 20 21 // RedisStore is a store for Redis 22 type RedisStore struct { 23 // RedisClientInterface represents a go-redis/redis client 24 client *redis.Client 25 options *Options 26 } 27 28 // NewRedis creates a new store to Redis instance(s) 29 func NewRedis(client *redis.Client, options *Options) *RedisStore { 30 if options == nil { 31 options = &Options{} 32 } 33 34 return &RedisStore{ 35 client: client, 36 options: options, 37 } 38 } 39 40 // Get returns data stored from a given key 41 func (s *RedisStore) Get(key string) (interface{}, error) { 42 return s.client.Get(key).Result() 43 } 44 45 // TTL returns a expiration time 46 func (s *RedisStore) TTL(key string) (time.Duration, error) { 47 return s.client.TTL(key).Result() 48 } 49 50 // Set defines data in Redis for given key identifier 51 func (s *RedisStore) Set(key string, value interface{}, options *Options) error { 52 if options == nil { 53 options = s.options 54 } 55 56 err := s.client.Set(key, value, options.ExpirationValue()).Err() 57 if err != nil { 58 return err 59 } 60 61 if tags := options.TagsValue(); len(tags) > 0 { 62 s.setTags(key, tags) 63 } 64 65 return nil 66 } 67 68 func (s *RedisStore) setTags(key string, tags []string) { 69 for _, tag := range tags { 70 var tagKey = fmt.Sprintf(RedisTagPattern, tag) 71 var cacheKeys = s.getCacheKeysForTag(tagKey) 72 73 var alreadyInserted = false 74 for _, cacheKey := range cacheKeys { 75 if cacheKey == key { 76 alreadyInserted = true 77 break 78 } 79 } 80 81 if !alreadyInserted { 82 cacheKeys = append(cacheKeys, key) 83 } 84 85 _ = s.Set(tagKey, strings.Join(cacheKeys, ","), &Options{ 86 Expiration: 720 * time.Hour, 87 }) 88 } 89 } 90 91 func (s *RedisStore) getCacheKeysForTag(tagKey string) []string { 92 var cacheKeys []string 93 if result, err := s.Get(tagKey); err == nil && result != "" { 94 if str, ok := result.(string); ok { 95 cacheKeys = strings.Split(str, ",") 96 } 97 } 98 return cacheKeys 99 } 100 101 // Delete removes data from Redis for given key identifier 102 func (s *RedisStore) Delete(key string) error { 103 _, err := s.client.Del(key).Result() 104 return err 105 } 106 107 // Invalidate invalidates some cache data in Redis for given options 108 func (s *RedisStore) Invalidate(options InvalidateOptions) error { 109 if tags := options.TagsValue(); len(tags) > 0 { 110 for _, tag := range tags { 111 var tagKey = fmt.Sprintf(RedisTagPattern, tag) 112 var cacheKeys = s.getCacheKeysForTag(tagKey) 113 114 for _, cacheKey := range cacheKeys { 115 _ = s.Delete(cacheKey) 116 } 117 118 _ = s.Delete(tagKey) 119 } 120 } 121 122 return nil 123 } 124 125 // GetType returns the store type 126 func (s *RedisStore) GetType() string { 127 return RedisType 128 } 129 130 // Clear resets all data in the store 131 func (s *RedisStore) Clear() error { 132 if err := s.client.FlushAll().Err(); err != nil { 133 return err 134 } 135 136 return nil 137 }