remotecache.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package remotecache
  2. import (
  3. "bytes"
  4. "context"
  5. "encoding/gob"
  6. "errors"
  7. "time"
  8. "github.com/grafana/grafana/pkg/infra/log"
  9. "github.com/grafana/grafana/pkg/registry"
  10. "github.com/grafana/grafana/pkg/services/sqlstore"
  11. "github.com/grafana/grafana/pkg/setting"
  12. )
  13. var (
  14. // ErrCacheItemNotFound is returned if cache does not exist
  15. ErrCacheItemNotFound = errors.New("cache item not found")
  16. // ErrInvalidCacheType is returned if the type is invalid
  17. ErrInvalidCacheType = errors.New("invalid remote cache name")
  18. defaultMaxCacheExpiration = time.Hour * 24
  19. )
  20. func init() {
  21. registry.RegisterService(&RemoteCache{})
  22. }
  23. // CacheStorage allows the caller to set, get and delete items in the cache.
  24. // Cached items are stored as byte arrays and marshalled using "encoding/gob"
  25. // so any struct added to the cache needs to be registred with `remotecache.Register`
  26. // ex `remotecache.Register(CacheableStruct{})``
  27. type CacheStorage interface {
  28. // Get reads object from Cache
  29. Get(key string) (interface{}, error)
  30. // Set sets an object into the cache. if `expire` is set to zero it will default to 24h
  31. Set(key string, value interface{}, expire time.Duration) error
  32. // Delete object from cache
  33. Delete(key string) error
  34. }
  35. // RemoteCache allows Grafana to cache data outside its own process
  36. type RemoteCache struct {
  37. log log.Logger
  38. client CacheStorage
  39. SQLStore *sqlstore.SqlStore `inject:""`
  40. Cfg *setting.Cfg `inject:""`
  41. }
  42. // Get reads object from Cache
  43. func (ds *RemoteCache) Get(key string) (interface{}, error) {
  44. return ds.client.Get(key)
  45. }
  46. // Set sets an object into the cache. if `expire` is set to zero it will default to 24h
  47. func (ds *RemoteCache) Set(key string, value interface{}, expire time.Duration) error {
  48. if expire == 0 {
  49. expire = defaultMaxCacheExpiration
  50. }
  51. return ds.client.Set(key, value, expire)
  52. }
  53. // Delete object from cache
  54. func (ds *RemoteCache) Delete(key string) error {
  55. return ds.client.Delete(key)
  56. }
  57. // Init initializes the service
  58. func (ds *RemoteCache) Init() error {
  59. ds.log = log.New("cache.remote")
  60. var err error
  61. ds.client, err = createClient(ds.Cfg.RemoteCacheOptions, ds.SQLStore)
  62. return err
  63. }
  64. // Run start the backend processes for cache clients
  65. func (ds *RemoteCache) Run(ctx context.Context) error {
  66. //create new interface if more clients need GC jobs
  67. backgroundjob, ok := ds.client.(registry.BackgroundService)
  68. if ok {
  69. return backgroundjob.Run(ctx)
  70. }
  71. <-ctx.Done()
  72. return ctx.Err()
  73. }
  74. func createClient(opts *setting.RemoteCacheOptions, sqlstore *sqlstore.SqlStore) (CacheStorage, error) {
  75. if opts.Name == redisCacheType {
  76. return newRedisStorage(opts), nil
  77. }
  78. if opts.Name == memcachedCacheType {
  79. return newMemcachedStorage(opts), nil
  80. }
  81. if opts.Name == databaseCacheType {
  82. return newDatabaseCache(sqlstore), nil
  83. }
  84. return nil, ErrInvalidCacheType
  85. }
  86. // Register records a type, identified by a value for that type, under its
  87. // internal type name. That name will identify the concrete type of a value
  88. // sent or received as an interface variable. Only types that will be
  89. // transferred as implementations of interface values need to be registered.
  90. // Expecting to be used only during initialization, it panics if the mapping
  91. // between types and names is not a bijection.
  92. func Register(value interface{}) {
  93. gob.Register(value)
  94. }
  95. type cachedItem struct {
  96. Val interface{}
  97. }
  98. func encodeGob(item *cachedItem) ([]byte, error) {
  99. buf := bytes.NewBuffer(nil)
  100. err := gob.NewEncoder(buf).Encode(item)
  101. return buf.Bytes(), err
  102. }
  103. func decodeGob(data []byte, out *cachedItem) error {
  104. buf := bytes.NewBuffer(data)
  105. return gob.NewDecoder(buf).Decode(&out)
  106. }