Skip to content

Commit

Permalink
Chore: Remote cache key prefix (#59838)
Browse files Browse the repository at this point in the history
* attempt to implement a remote cache key prefix

* add a test for the prefix store

* oh, linter
  • Loading branch information
zserge committed Dec 6, 2022
1 parent 932349b commit 3978502
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 11 deletions.
3 changes: 3 additions & 0 deletions conf/defaults.ini
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ type = database
# memcache: 127.0.0.1:11211
connstr =

# prefix prepended to all the keys in the remote cache
prefix =

#################################### Data proxy ###########################
[dataproxy]

Expand Down
3 changes: 3 additions & 0 deletions conf/sample.ini
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@
# memcache: 127.0.0.1:11211
;connstr =

# prefix prepended to all the keys in the remote cache
; prefix =

#################################### Data proxy ###########################
[dataproxy]

Expand Down
41 changes: 30 additions & 11 deletions pkg/infra/remotecache/remotecache.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,24 @@ func (ds *RemoteCache) Run(ctx context.Context) error {
return ctx.Err()
}

func createClient(opts *setting.RemoteCacheOptions, sqlstore db.DB) (CacheStorage, error) {
if opts.Name == redisCacheType {
return newRedisStorage(opts)
func createClient(opts *setting.RemoteCacheOptions, sqlstore db.DB) (cache CacheStorage, err error) {
switch opts.Name {
case redisCacheType:
cache, err = newRedisStorage(opts)
case memcachedCacheType:
cache = newMemcachedStorage(opts)
case databaseCacheType:
cache = newDatabaseCache(sqlstore)
default:
return nil, ErrInvalidCacheType
}

if opts.Name == memcachedCacheType {
return newMemcachedStorage(opts), nil
if err != nil {
return cache, err
}

if opts.Name == databaseCacheType {
return newDatabaseCache(sqlstore), nil
if opts.Prefix != "" {
cache = &prefixCacheStorage{cache: cache, prefix: opts.Prefix}
}

return nil, ErrInvalidCacheType
return cache, nil
}

// Register records a type, identified by a value for that type, under its
Expand All @@ -137,3 +141,18 @@ func decodeGob(data []byte, out *cachedItem) error {
buf := bytes.NewBuffer(data)
return gob.NewDecoder(buf).Decode(&out)
}

type prefixCacheStorage struct {
cache CacheStorage
prefix string
}

func (pcs *prefixCacheStorage) Get(ctx context.Context, key string) (interface{}, error) {
return pcs.cache.Get(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) Delete(ctx context.Context, key string) error {
return pcs.cache.Delete(ctx, pcs.prefix+key)
}
25 changes: 25 additions & 0 deletions pkg/infra/remotecache/remotecache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/setting"
)

Expand Down Expand Up @@ -88,3 +89,27 @@ func canNotFetchExpiredItems(t *testing.T, client CacheStorage) {
_, err = client.Get(context.Background(), "key1")
assert.Equal(t, err, ErrCacheItemNotFound)
}

func TestCachePrefix(t *testing.T) {
db := db.InitTestDB(t)
cache := &databaseCache{
SQLStore: db,
log: log.New("remotecache.database"),
}
prefixCache := &prefixCacheStorage{cache: cache, prefix: "test/"}

// Set a value (with a prefix)
err := prefixCache.Set(context.Background(), "foo", "bar", time.Hour)
require.NoError(t, err)
// Get a value (with a prefix)
v, err := prefixCache.Get(context.Background(), "foo")
require.NoError(t, err)
require.Equal(t, "bar", v)
// Get a value directly from the underlying cache, ensure the prefix is in the key
v, err = cache.Get(context.Background(), "test/foo")
require.NoError(t, err)
require.Equal(t, "bar", v)
// Get a value directly from the underlying cache without a prefix, should not be there
_, err = cache.Get(context.Background(), "foo")
require.Error(t, err)
}
3 changes: 3 additions & 0 deletions pkg/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -1120,10 +1120,12 @@ func (cfg *Cfg) Load(args CommandLineArgs) error {
cacheServer := iniFile.Section("remote_cache")
dbName := valueAsString(cacheServer, "type", "database")
connStr := valueAsString(cacheServer, "connstr", "")
prefix := valueAsString(cacheServer, "prefix", "")

cfg.RemoteCacheOptions = &RemoteCacheOptions{
Name: dbName,
ConnStr: connStr,
Prefix: prefix,
}

geomapSection := iniFile.Section("geomap")
Expand Down Expand Up @@ -1159,6 +1161,7 @@ func valueAsString(section *ini.Section, keyName string, defaultValue string) st
type RemoteCacheOptions struct {
Name string
ConnStr string
Prefix string
}

func (cfg *Cfg) readLDAPConfig() {
Expand Down

0 comments on commit 3978502

Please sign in to comment.