fix(redis): namespace cache keys when no prefix is set

With an empty prefix, Clear deleted every key in the Redis database, including keys of other applications. Cache keys now start with gmp: by default. Existing cache entries become unreachable after the upgrade and expire by TTL.
This commit is contained in:
2026-11-03 00:49:02 +00:00
parent 4c5d01aef3
commit cff11f2b25
3 changed files with 43 additions and 5 deletions
+9 -1
View File
@@ -83,7 +83,15 @@ type RedisClientConfig struct {
// entry.
const defaultTTL = 60 * time.Second
// DefaultKeyPrefix namespaces cache keys when no prefix is configured, so Clear
// and CountQueries never touch keys of other applications on a shared Redis.
const DefaultKeyPrefix = "gmp:"
func New(redisClientConfig *RedisClientConfig) (*RedisConfig, error) {
prefix := redisClientConfig.Prefix
if prefix == "" {
prefix = DefaultKeyPrefix
}
c := &RedisConfig{
client: redis.NewClient(&redis.Options{
Addr: redisClientConfig.RedisServer,
@@ -91,7 +99,7 @@ func New(redisClientConfig *RedisClientConfig) (*RedisConfig, error) {
DB: redisClientConfig.RedisDB,
}),
ctx: context.Background(),
prefix: redisClientConfig.Prefix,
prefix: prefix,
builderPool: &sync.Pool{
New: func() any {
return &strings.Builder{}
+30
View File
@@ -0,0 +1,30 @@
package libpack_cache_redis
import (
"testing"
"github.com/alicebob/miniredis/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Pins theorems/Theorems/RedisClear.lean: with no configured prefix, Clear must still spare foreign keys.
func TestClear_DefaultPrefixSparesForeignKeys(t *testing.T) {
t.Parallel()
s, err := miniredis.Run()
require.NoError(t, err)
t.Cleanup(s.Close)
require.NoError(t, s.Set("other-app:session", "keep"))
c, err := New(&RedisClientConfig{RedisServer: s.Addr()})
require.NoError(t, err)
require.NoError(t, c.Set("q1", []byte("v"), 0))
require.NoError(t, c.Clear())
assert.True(t, s.Exists("other-app:session"), "foreign key was deleted")
_, found, err := c.Get("q1")
require.NoError(t, err)
assert.False(t, found, "own key must be cleared")
}
+4 -4
View File
@@ -131,11 +131,11 @@ func (suite *RedisConfigSuite) TestGetKeys() {
err = suite.redisConfig.Set("otherkey", []byte("othervalue"), ttl)
assert.NoError(suite.T(), err)
keys, _ := suite.redisConfig.client.Keys(suite.redisConfig.ctx, "testkey*").Result()
expectedKeys := []string{"testkey1", "testkey2"}
keys, _ := suite.redisConfig.client.Keys(suite.redisConfig.ctx, DefaultKeyPrefix+"testkey*").Result()
expectedKeys := []string{DefaultKeyPrefix + "testkey1", DefaultKeyPrefix + "testkey2"}
assert.ElementsMatch(suite.T(), expectedKeys, keys)
suite.redisConfig.client.Del(suite.redisConfig.ctx, "testkey1", "testkey2", "otherkey")
suite.redisConfig.client.Del(suite.redisConfig.ctx, DefaultKeyPrefix+"testkey1", DefaultKeyPrefix+"testkey2", DefaultKeyPrefix+"otherkey")
}
func (suite *RedisConfigSuite) TestGetKeysCount() {
@@ -154,5 +154,5 @@ func (suite *RedisConfigSuite) TestGetKeysCount() {
assert.NoError(suite.T(), err)
assert.Equal(suite.T(), int64(3), count3)
suite.redisConfig.client.Del(suite.redisConfig.ctx, "testkey1", "testkey2", "otherkey")
suite.redisConfig.client.Del(suite.redisConfig.ctx, DefaultKeyPrefix+"testkey1", DefaultKeyPrefix+"testkey2", DefaultKeyPrefix+"otherkey")
}