diff --git a/pkg/infra/remotecache/database_storage.go b/pkg/infra/remotecache/database_storage.go index be5be00011d..59c5b96fee1 100644 --- a/pkg/infra/remotecache/database_storage.go +++ b/pkg/infra/remotecache/database_storage.go @@ -54,10 +54,9 @@ func (dc *databaseCache) internalRunGC() { } } -func (dc *databaseCache) Get(ctx context.Context, key string) (interface{}, error) { +func (dc *databaseCache) GetByteArray(ctx context.Context, key string) ([]byte, error) { cacheHit := CacheData{} - item := &cachedItem{} err := dc.SQLStore.WithDbSession(ctx, func(session *db.Session) error { exist, err := session.Where("cache_key= ?", key).Get(&cacheHit) @@ -80,23 +79,27 @@ func (dc *databaseCache) Get(ctx context.Context, key string) (interface{}, erro } } - if err = dc.codec.Decode(ctx, cacheHit.Data, item); err != nil { - return err - } - return nil }) + return cacheHit.Data, err +} + +func (dc *databaseCache) Get(ctx context.Context, key string) (interface{}, error) { + bytes, err := dc.GetByteArray(ctx, key) + if err != nil { + return nil, err + } + + item := &cachedItem{} + if err = dc.codec.Decode(ctx, bytes, item); err != nil { + return nil, err + } + return item.Val, err } -func (dc *databaseCache) Set(ctx context.Context, key string, value interface{}, expire time.Duration) error { - item := &cachedItem{Val: value} - data, err := dc.codec.Encode(ctx, item) - if err != nil { - return err - } - +func (dc *databaseCache) SetByteArray(ctx context.Context, key string, data []byte, expire time.Duration) error { return dc.SQLStore.WithDbSession(ctx, func(session *db.Session) error { var expiresInSeconds int64 if expire != 0 { @@ -126,6 +129,16 @@ func (dc *databaseCache) Set(ctx context.Context, key string, value interface{}, }) } +func (dc *databaseCache) Set(ctx context.Context, key string, value interface{}, expire time.Duration) error { + item := &cachedItem{Val: value} + data, err := dc.codec.Encode(ctx, item) + if err != nil { + return err + } + + return dc.SetByteArray(ctx, key, data, expire) +} + func (dc *databaseCache) Delete(ctx context.Context, key string) error { return dc.SQLStore.WithDbSession(ctx, func(session *db.Session) error { sql := "DELETE FROM cache_data WHERE cache_key=?" diff --git a/pkg/infra/remotecache/memcached_storage.go b/pkg/infra/remotecache/memcached_storage.go index f8601eb1a2d..339c7bf6324 100644 --- a/pkg/infra/remotecache/memcached_storage.go +++ b/pkg/infra/remotecache/memcached_storage.go @@ -2,6 +2,7 @@ package remotecache import ( "context" + "errors" "time" "github.com/bradfitz/gomemcache/memcache" @@ -39,29 +40,29 @@ func (s *memcachedStorage) Set(ctx context.Context, key string, val interface{}, return err } + return s.SetByteArray(ctx, key, bytes, expires) +} + +// SetByteArray stores an byte array in the cache +func (s *memcachedStorage) SetByteArray(ctx context.Context, key string, data []byte, expires time.Duration) error { var expiresInSeconds int64 if expires != 0 { expiresInSeconds = int64(expires) / int64(time.Second) } - memcachedItem := newItem(key, bytes, int32(expiresInSeconds)) + memcachedItem := newItem(key, data, int32(expiresInSeconds)) return s.c.Set(memcachedItem) } // Get gets value by given key in the cache. func (s *memcachedStorage) Get(ctx context.Context, key string) (interface{}, error) { - memcachedItem, err := s.c.Get(key) - if err != nil && err.Error() == "memcache: cache miss" { - return nil, ErrCacheItemNotFound - } - + bytes, err := s.GetByteArray(ctx, key) if err != nil { return nil, err } item := &cachedItem{} - - err = s.codec.Decode(ctx, memcachedItem.Value, item) + err = s.codec.Decode(ctx, bytes, item) if err != nil { return nil, err } @@ -69,6 +70,20 @@ func (s *memcachedStorage) Get(ctx context.Context, key string) (interface{}, er return item.Val, nil } +// GetByteArray returns the cached value as an byte array +func (s *memcachedStorage) GetByteArray(ctx context.Context, key string) ([]byte, error) { + memcachedItem, err := s.c.Get(key) + if errors.Is(err, memcache.ErrCacheMiss) { + return nil, ErrCacheItemNotFound + } + + if err != nil { + return nil, err + } + + return memcachedItem.Value, nil +} + // Delete delete a key from the cache func (s *memcachedStorage) Delete(ctx context.Context, key string) error { return s.c.Delete(key) diff --git a/pkg/infra/remotecache/redis_storage.go b/pkg/infra/remotecache/redis_storage.go index f8ed10d5bb8..4d646379d45 100644 --- a/pkg/infra/remotecache/redis_storage.go +++ b/pkg/infra/remotecache/redis_storage.go @@ -93,26 +93,43 @@ func (s *redisStorage) Set(ctx context.Context, key string, val interface{}, exp if err != nil { return err } - status := s.c.Set(ctx, key, string(value), expires) + + return s.SetByteArray(ctx, key, value, expires) +} + +// Set sets value to a given key +func (s *redisStorage) SetByteArray(ctx context.Context, key string, data []byte, expires time.Duration) error { + status := s.c.Set(ctx, key, data, expires) return status.Err() } // Get gets value by given key in session. func (s *redisStorage) Get(ctx context.Context, key string) (interface{}, error) { - v := s.c.Get(ctx, key) + v, err := s.GetByteArray(ctx, key) + + if err.Error() == "EOF" { + return nil, ErrCacheItemNotFound + } + + if err != nil { + return nil, err + } item := &cachedItem{} - err := s.codec.Decode(ctx, []byte(v.Val()), item) + err = s.codec.Decode(ctx, v, item) if err == nil { return item.Val, nil } - if err.Error() == "EOF" { - return nil, ErrCacheItemNotFound - } + return nil, err } +// GetByteArray returns the value as byte array +func (s *redisStorage) GetByteArray(ctx context.Context, key string) ([]byte, error) { + return s.c.Get(ctx, key).Bytes() +} + // Delete delete a key from session. func (s *redisStorage) Delete(ctx context.Context, key string) error { cmd := s.c.Del(ctx, key) diff --git a/pkg/infra/remotecache/remotecache.go b/pkg/infra/remotecache/remotecache.go index dcbd81f1dd5..6e37d0426ee 100644 --- a/pkg/infra/remotecache/remotecache.go +++ b/pkg/infra/remotecache/remotecache.go @@ -61,6 +61,12 @@ type CacheStorage interface { // Set sets an object into the cache. if `expire` is set to zero it will default to 24h Set(ctx context.Context, key string, value interface{}, expire time.Duration) error + // GetByteArray gets the cache value as an byte array + GetByteArray(ctx context.Context, key string) ([]byte, error) + + // SetByteArray saves the value as an byte array. if `expire` is set to zero it will default to 24h + SetByteArray(ctx context.Context, key string, value []byte, expire time.Duration) error + // Delete object from cache Delete(ctx context.Context, key string) error } @@ -78,6 +84,16 @@ func (ds *RemoteCache) Get(ctx context.Context, key string) (interface{}, error) return ds.client.Get(ctx, key) } +// GetByteArray returns the cached value as an byte array +func (ds *RemoteCache) GetByteArray(ctx context.Context, key string) ([]byte, error) { + return ds.client.GetByteArray(ctx, key) +} + +// SetByteArray stored the byte array in the cache +func (ds *RemoteCache) SetByteArray(ctx context.Context, key string, value []byte, expire time.Duration) error { + return ds.client.SetByteArray(ctx, key, value, expire) +} + // Set sets an object into the cache. if `expire` is set to zero it will default to 24h func (ds *RemoteCache) Set(ctx context.Context, key string, value interface{}, expire time.Duration) error { if expire == 0 { @@ -186,9 +202,15 @@ type prefixCacheStorage struct { func (pcs *prefixCacheStorage) Get(ctx context.Context, key string) (interface{}, error) { return pcs.cache.Get(ctx, pcs.prefix+key) } +func (pcs *prefixCacheStorage) GetByteArray(ctx context.Context, key string) ([]byte, error) { + return pcs.cache.GetByteArray(ctx, pcs.prefix+key) +} func (pcs *prefixCacheStorage) Set(ctx context.Context, key string, value interface{}, expire time.Duration) error { return pcs.cache.Set(ctx, pcs.prefix+key, value, expire) } +func (pcs *prefixCacheStorage) SetByteArray(ctx context.Context, key string, value []byte, expire time.Duration) error { + return pcs.cache.SetByteArray(ctx, pcs.prefix+key, value, expire) +} func (pcs *prefixCacheStorage) Delete(ctx context.Context, key string) error { return pcs.cache.Delete(ctx, pcs.prefix+key) }