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  }