github.com/msales/pkg/v3@v3.24.0/cache/redis.go (about)

     1  package cache
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/go-redis/redis"
     7  )
     8  
     9  // RedisOptionsFunc represents an configuration function for Redis.
    10  type RedisOptionsFunc func(*redis.UniversalOptions)
    11  
    12  // WithPoolSize configures the Redis pool size.
    13  func WithPoolSize(size int) RedisOptionsFunc {
    14  	return func(o *redis.UniversalOptions) {
    15  		o.PoolSize = size
    16  	}
    17  }
    18  
    19  // WithPoolTimeout configures the Redis pool timeout.
    20  func WithPoolTimeout(timeout time.Duration) RedisOptionsFunc {
    21  	return func(o *redis.UniversalOptions) {
    22  		o.PoolTimeout = timeout
    23  	}
    24  }
    25  
    26  // WithReadTimeout configures the Redis read timeout.
    27  func WithReadTimeout(timeout time.Duration) RedisOptionsFunc {
    28  	return func(o *redis.UniversalOptions) {
    29  		o.ReadTimeout = timeout
    30  	}
    31  }
    32  
    33  // WithWriteTimeout configures the Redis write timeout.
    34  func WithWriteTimeout(timeout time.Duration) RedisOptionsFunc {
    35  	return func(o *redis.UniversalOptions) {
    36  		o.WriteTimeout = timeout
    37  	}
    38  }
    39  
    40  type redisCache struct {
    41  	client  redis.UniversalClient
    42  	decoder decoder
    43  }
    44  
    45  // NewRedis create a new Redis cache instance.
    46  func NewRedis(uri string, opts ...RedisOptionsFunc) (Cache, error) {
    47  	o, err := redis.ParseURL(uri)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  
    52  	uo := &redis.UniversalOptions{
    53  		Addrs:         []string{o.Addr},
    54  		RouteRandomly: true,
    55  	}
    56  
    57  	for _, opt := range opts {
    58  		opt(uo)
    59  	}
    60  
    61  	c := redis.NewUniversalClient(uo)
    62  
    63  	return &redisCache{
    64  		client:  c,
    65  		decoder: stringDecoder{},
    66  	}, nil
    67  }
    68  
    69  func NewRedisUniversal(addrs []string, opts ...RedisOptionsFunc) (Cache, error) {
    70  	uo := &redis.UniversalOptions{
    71  		Addrs:         addrs,
    72  		RouteRandomly: true,
    73  	}
    74  
    75  	for _, opt := range opts {
    76  		opt(uo)
    77  	}
    78  
    79  	c := redis.NewUniversalClient(uo)
    80  
    81  	return &redisCache{
    82  		client:  c,
    83  		decoder: stringDecoder{},
    84  	}, nil
    85  }
    86  
    87  // Get gets the item for the given key.
    88  func (c redisCache) Get(key string) *Item {
    89  	b, err := c.client.Get(key).Bytes()
    90  	if err == redis.Nil {
    91  		err = ErrCacheMiss
    92  	}
    93  
    94  	return &Item{
    95  		decoder: c.decoder,
    96  		value:   b,
    97  		err:     err,
    98  	}
    99  }
   100  
   101  // GetMulti gets the items for the given keys.
   102  func (c redisCache) GetMulti(keys ...string) ([]*Item, error) {
   103  	val, err := c.client.MGet(keys...).Result()
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	i := []*Item{}
   109  	for _, v := range val {
   110  		var err = ErrCacheMiss
   111  		var b []byte
   112  		if v != nil {
   113  			b = []byte(v.(string))
   114  			err = nil
   115  		}
   116  
   117  		i = append(i, &Item{
   118  			decoder: c.decoder,
   119  			value:   b,
   120  			err:     err,
   121  		})
   122  	}
   123  
   124  	return i, nil
   125  }
   126  
   127  // Set sets the item in the cache.
   128  func (c redisCache) Set(key string, value interface{}, expire time.Duration) error {
   129  	return c.client.Set(key, value, expire).Err()
   130  }
   131  
   132  // Add sets the item in the cache, but only if the key does not already exist.
   133  func (c redisCache) Add(key string, value interface{}, expire time.Duration) error {
   134  	if !c.client.SetNX(key, value, expire).Val() {
   135  		return ErrNotStored
   136  	}
   137  	return nil
   138  }
   139  
   140  // Replace sets the item in the cache, but only if the key already exists.
   141  func (c redisCache) Replace(key string, value interface{}, expire time.Duration) error {
   142  	if !c.client.SetXX(key, value, expire).Val() {
   143  		return ErrNotStored
   144  	}
   145  	return nil
   146  }
   147  
   148  // Delete deletes the item with the given key.
   149  func (c redisCache) Delete(key string) error {
   150  	return c.client.Del(key).Err()
   151  }
   152  
   153  // Inc increments a key by the value.
   154  func (c redisCache) Inc(key string, value uint64) (int64, error) {
   155  	return c.client.IncrBy(key, int64(value)).Result()
   156  }
   157  
   158  // Dec decrements a key by the value.
   159  func (c redisCache) Dec(key string, value uint64) (int64, error) {
   160  	return c.client.DecrBy(key, int64(value)).Result()
   161  }