redis_storage.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package remotecache
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "time"
  7. "github.com/grafana/grafana/pkg/setting"
  8. "github.com/grafana/grafana/pkg/util/errutil"
  9. redis "gopkg.in/redis.v2"
  10. )
  11. const redisCacheType = "redis"
  12. type redisStorage struct {
  13. c *redis.Client
  14. }
  15. // parseRedisConnStr parses k=v pairs in csv and builds a redis Options object
  16. func parseRedisConnStr(connStr string) (*redis.Options, error) {
  17. keyValueCSV := strings.Split(connStr, ",")
  18. options := &redis.Options{Network: "tcp"}
  19. for _, rawKeyValue := range keyValueCSV {
  20. keyValueTuple := strings.Split(rawKeyValue, "=")
  21. if len(keyValueTuple) != 2 {
  22. return nil, fmt.Errorf("incorrect redis connection string format detected for '%v', format is key=value,key=value", rawKeyValue)
  23. }
  24. connKey := keyValueTuple[0]
  25. connVal := keyValueTuple[1]
  26. switch connKey {
  27. case "addr":
  28. options.Addr = connVal
  29. case "password":
  30. options.Password = connVal
  31. case "db":
  32. i, err := strconv.ParseInt(connVal, 10, 64)
  33. if err != nil {
  34. return nil, errutil.Wrap("value for db in redis connection string must be a number", err)
  35. }
  36. options.DB = i
  37. case "pool_size":
  38. i, err := strconv.Atoi(connVal)
  39. if err != nil {
  40. return nil, errutil.Wrap("value for pool_size in redis connection string must be a number", err)
  41. }
  42. options.PoolSize = i
  43. default:
  44. return nil, fmt.Errorf("unrecorgnized option '%v' in redis connection string", connVal)
  45. }
  46. }
  47. return options, nil
  48. }
  49. func newRedisStorage(opts *setting.RemoteCacheOptions) (*redisStorage, error) {
  50. opt, err := parseRedisConnStr(opts.ConnStr)
  51. if err != nil {
  52. return nil, err
  53. }
  54. return &redisStorage{c: redis.NewClient(opt)}, nil
  55. }
  56. // Set sets value to given key in session.
  57. func (s *redisStorage) Set(key string, val interface{}, expires time.Duration) error {
  58. item := &cachedItem{Val: val}
  59. value, err := encodeGob(item)
  60. if err != nil {
  61. return err
  62. }
  63. status := s.c.SetEx(key, expires, string(value))
  64. return status.Err()
  65. }
  66. // Get gets value by given key in session.
  67. func (s *redisStorage) Get(key string) (interface{}, error) {
  68. v := s.c.Get(key)
  69. item := &cachedItem{}
  70. err := decodeGob([]byte(v.Val()), item)
  71. if err == nil {
  72. return item.Val, nil
  73. }
  74. if err.Error() == "EOF" {
  75. return nil, ErrCacheItemNotFound
  76. }
  77. return nil, err
  78. }
  79. // Delete delete a key from session.
  80. func (s *redisStorage) Delete(key string) error {
  81. cmd := s.c.Del(key)
  82. return cmd.Err()
  83. }