Chore: Remote cache key prefix (#59838)

* attempt to implement a remote cache key prefix

* add a test for the prefix store

* oh, linter
This commit is contained in:
Serge Zaitsev 2022-12-06 13:20:49 +01:00 committed by GitHub
parent 932349b5ab
commit 3978502d83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 64 additions and 11 deletions

View File

@ -162,6 +162,9 @@ type = database
# memcache: 127.0.0.1:11211 # memcache: 127.0.0.1:11211
connstr = connstr =
# prefix prepended to all the keys in the remote cache
prefix =
#################################### Data proxy ########################### #################################### Data proxy ###########################
[dataproxy] [dataproxy]

View File

@ -169,6 +169,9 @@
# memcache: 127.0.0.1:11211 # memcache: 127.0.0.1:11211
;connstr = ;connstr =
# prefix prepended to all the keys in the remote cache
; prefix =
#################################### Data proxy ########################### #################################### Data proxy ###########################
[dataproxy] [dataproxy]

View File

@ -97,20 +97,24 @@ func (ds *RemoteCache) Run(ctx context.Context) error {
return ctx.Err() return ctx.Err()
} }
func createClient(opts *setting.RemoteCacheOptions, sqlstore db.DB) (CacheStorage, error) { func createClient(opts *setting.RemoteCacheOptions, sqlstore db.DB) (cache CacheStorage, err error) {
if opts.Name == redisCacheType { switch opts.Name {
return newRedisStorage(opts) case redisCacheType:
cache, err = newRedisStorage(opts)
case memcachedCacheType:
cache = newMemcachedStorage(opts)
case databaseCacheType:
cache = newDatabaseCache(sqlstore)
default:
return nil, ErrInvalidCacheType
} }
if err != nil {
if opts.Name == memcachedCacheType { return cache, err
return newMemcachedStorage(opts), nil
} }
if opts.Prefix != "" {
if opts.Name == databaseCacheType { cache = &prefixCacheStorage{cache: cache, prefix: opts.Prefix}
return newDatabaseCache(sqlstore), nil
} }
return cache, nil
return nil, ErrInvalidCacheType
} }
// Register records a type, identified by a value for that type, under its // Register records a type, identified by a value for that type, under its
@ -137,3 +141,18 @@ func decodeGob(data []byte, out *cachedItem) error {
buf := bytes.NewBuffer(data) buf := bytes.NewBuffer(data)
return gob.NewDecoder(buf).Decode(&out) 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)
}

View File

@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/db" "github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/setting"
) )
@ -88,3 +89,27 @@ func canNotFetchExpiredItems(t *testing.T, client CacheStorage) {
_, err = client.Get(context.Background(), "key1") _, err = client.Get(context.Background(), "key1")
assert.Equal(t, err, ErrCacheItemNotFound) 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)
}

View File

@ -1120,10 +1120,12 @@ func (cfg *Cfg) Load(args CommandLineArgs) error {
cacheServer := iniFile.Section("remote_cache") cacheServer := iniFile.Section("remote_cache")
dbName := valueAsString(cacheServer, "type", "database") dbName := valueAsString(cacheServer, "type", "database")
connStr := valueAsString(cacheServer, "connstr", "") connStr := valueAsString(cacheServer, "connstr", "")
prefix := valueAsString(cacheServer, "prefix", "")
cfg.RemoteCacheOptions = &RemoteCacheOptions{ cfg.RemoteCacheOptions = &RemoteCacheOptions{
Name: dbName, Name: dbName,
ConnStr: connStr, ConnStr: connStr,
Prefix: prefix,
} }
geomapSection := iniFile.Section("geomap") geomapSection := iniFile.Section("geomap")
@ -1159,6 +1161,7 @@ func valueAsString(section *ini.Section, keyName string, defaultValue string) st
type RemoteCacheOptions struct { type RemoteCacheOptions struct {
Name string Name string
ConnStr string ConnStr string
Prefix string
} }
func (cfg *Cfg) readLDAPConfig() { func (cfg *Cfg) readLDAPConfig() {