package cache import ( "time" "github.com/go-redis/redis" "github.com/pkg/errors" "github.com/vmihailenco/msgpack" ) var ErrNotFound = errors.New("not found") // RedisCache implements caching layer for feeds using Redis // // Inside docker can be connected as: // docker exec -it redis redis-cli // View available keys: // 127.0.0.1:6379> keys * // type RedisCache struct { client *redis.Client } func NewRedisCache(redisURL string) (RedisCache, error) { opts, err := redis.ParseURL(redisURL) if err != nil { return RedisCache{}, err } client := redis.NewClient(opts) if err := client.Ping().Err(); err != nil { return RedisCache{}, err } return RedisCache{client: client}, nil } func (c RedisCache) Set(key, value string, ttl time.Duration) error { return c.client.Set(key, value, ttl).Err() } func (c RedisCache) Get(key string) (string, error) { val, err := c.client.Get(key).Result() if err == redis.Nil { return "", ErrNotFound } else { return val, err } } func (c RedisCache) SaveItem(key string, item interface{}, exp time.Duration) error { data, err := msgpack.Marshal(item) if err != nil { return err } return c.client.Set(key, data, exp).Err() } func (c RedisCache) GetItem(key string, item interface{}) error { data, err := c.client.Get(key).Bytes() if err == redis.Nil { return ErrNotFound } else if err != nil { return err } if err := msgpack.Unmarshal(data, item); err != nil { return err } return nil } func (c RedisCache) SetMap(key string, fields map[string]interface{}, exp time.Duration) error { if err := c.client.HMSet(key, fields).Err(); err != nil { return err } if err := c.client.TTL(key).Err(); err != nil { return err } return nil } func (c RedisCache) GetMap(key string, fields ...string) (map[string]string, error) { result, err := c.client.HMGet(key, fields...).Result() if err == redis.Nil { return nil, ErrNotFound } else if err != nil { return nil, err } data := map[string]string{} for idx, key := range fields { if result[idx] == nil { continue } data[key] = result[idx].(string) } if len(data) == 0 { return nil, ErrNotFound } return data, nil } func (c RedisCache) Invalidate(key... string) error { return c.client.Del(key...).Err() } func (c RedisCache) Close() error { return c.client.Close() }