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 }