grafana/pkg/infra/remotecache/redis_storage.go

99 lines
2.5 KiB
Go
Raw Normal View History

2019-03-08 13:49:16 -06:00
package remotecache
2019-02-23 09:12:37 -06:00
import (
"fmt"
"strconv"
"strings"
2019-02-23 09:12:37 -06:00
"time"
2019-03-03 14:48:00 -06:00
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util/errutil"
2019-02-23 09:12:37 -06:00
redis "gopkg.in/redis.v2"
)
2019-03-14 03:27:41 -05:00
const redisCacheType = "redis"
2019-02-23 09:12:37 -06:00
type redisStorage struct {
c *redis.Client
}
// parseRedisConnStr parses k=v pairs in csv and builds a redis Options object
func parseRedisConnStr(connStr string) (*redis.Options, error) {
keyValueCSV := strings.Split(connStr, ",")
options := &redis.Options{Network: "tcp"}
for _, rawKeyValue := range keyValueCSV {
keyValueTuple := strings.SplitN(rawKeyValue, "=", 2)
if len(keyValueTuple) != 2 {
if strings.HasPrefix(rawKeyValue, "password") {
// don't log the password
rawKeyValue = "password******"
}
return nil, fmt.Errorf("incorrect redis connection string format detected for '%v', format is key=value,key=value", rawKeyValue)
}
connKey := keyValueTuple[0]
connVal := keyValueTuple[1]
switch connKey {
case "addr":
options.Addr = connVal
case "password":
options.Password = connVal
case "db":
i, err := strconv.ParseInt(connVal, 10, 64)
if err != nil {
return nil, errutil.Wrap("value for db in redis connection string must be a number", err)
}
options.DB = i
case "pool_size":
i, err := strconv.Atoi(connVal)
if err != nil {
return nil, errutil.Wrap("value for pool_size in redis connection string must be a number", err)
}
options.PoolSize = i
default:
return nil, fmt.Errorf("unrecorgnized option '%v' in redis connection string", connVal)
}
2019-03-03 14:48:00 -06:00
}
return options, nil
}
func newRedisStorage(opts *setting.RemoteCacheOptions) (*redisStorage, error) {
opt, err := parseRedisConnStr(opts.ConnStr)
if err != nil {
return nil, err
}
return &redisStorage{c: redis.NewClient(opt)}, nil
2019-02-23 09:12:37 -06:00
}
// Set sets value to given key in session.
2019-03-05 08:15:05 -06:00
func (s *redisStorage) Set(key string, val interface{}, expires time.Duration) error {
item := &cachedItem{Val: val}
value, err := encodeGob(item)
2019-02-23 09:12:37 -06:00
if err != nil {
return err
}
2019-03-14 03:22:03 -05:00
status := s.c.SetEx(key, expires, string(value))
2019-02-23 09:12:37 -06:00
return status.Err()
}
// Get gets value by given key in session.
func (s *redisStorage) Get(key string) (interface{}, error) {
v := s.c.Get(key)
item := &cachedItem{}
err := decodeGob([]byte(v.Val()), item)
2019-02-23 09:12:37 -06:00
if err == nil {
return item.Val, nil
}
if err.Error() == "EOF" {
return nil, ErrCacheItemNotFound
}
return nil, err
2019-02-23 09:12:37 -06:00
}
// Delete delete a key from session.
func (s *redisStorage) Delete(key string) error {
cmd := s.c.Del(key)
return cmd.Err()
}