From 1047faadfbd53f7b0724cdcaf910d41e06e1fb1d Mon Sep 17 00:00:00 2001 From: Ming Deng Date: Mon, 26 Jun 2023 13:41:08 +0800 Subject: [PATCH] cache/redis: support skipEmptyPrefix option (#5264) --- CHANGELOG.md | 1 + client/cache/redis/redis.go | 25 +++++++++++------ client/cache/redis/redis_test.go | 48 ++++++++++++++++++++++++++++++++ client/cache/write_delete.go | 2 +- client/orm/cmd_utils_test.go | 3 +- 5 files changed, 68 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e222086..c358f69d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - [fix 5255: Check the rows.Err() if rows.Next() is false](https://github.com/beego/beego/pull/5256) - [orm: missing handling %COL% placeholder](https://github.com/beego/beego/pull/5257) - [fix: use of ioutil package](https://github.com/beego/beego/pull/5261) +- [cache/redis: support skipEmptyPrefix option ](https://github.com/beego/beego/pull/5264) ## ORM refactoring - [introducing internal/models pkg](https://github.com/beego/beego/pull/5238) diff --git a/client/cache/redis/redis.go b/client/cache/redis/redis.go index 8c38b474..f81b9325 100644 --- a/client/cache/redis/redis.go +++ b/client/cache/redis/redis.go @@ -51,10 +51,16 @@ type Cache struct { p *redis.Pool // redis connection pool conninfo string dbNum int + // key actually is prefix. key string password string maxIdle int + // skipEmptyPrefix for backward compatible, + // check function associate + // see https://github.com/beego/beego/issues/5248 + skipEmptyPrefix bool + // Timeout value (less than the redis server's timeout value) timeout time.Duration } @@ -83,6 +89,9 @@ func (rc *Cache) do(commandName string, args ...interface{}) (interface{}, error // associate with config key. func (rc *Cache) associate(originKey interface{}) string { + if rc.key == "" && rc.skipEmptyPrefix { + return fmt.Sprintf("%s", originKey) + } return fmt.Sprintf("%s:%s", rc.key, originKey) } @@ -192,7 +201,7 @@ func (rc *Cache) Scan(pattern string) (keys []string, err error) { } // StartAndGC starts the redis cache adapter. -// config: must be in this format {"key":"collection key","conn":"connection info","dbNum":"0"} +// config: must be in this format {"key":"collection key","conn":"connection info","dbNum":"0", "skipEmptyPrefix":"true"} // Cached items in redis are stored forever, no garbage collection happens func (rc *Cache) StartAndGC(config string) error { var cf map[string]string @@ -215,21 +224,19 @@ func (rc *Cache) StartAndGC(config string) error { cf["conn"] = cf["conn"][i+1:] } - if _, ok := cf["dbNum"]; !ok { - cf["dbNum"] = "0" - } - if _, ok := cf["password"]; !ok { - cf["password"] = "" + if v, ok := cf["dbNum"]; ok { + rc.dbNum, _ = strconv.Atoi(v) } if _, ok := cf["maxIdle"]; !ok { cf["maxIdle"] = "3" } - if _, ok := cf["timeout"]; !ok { - cf["timeout"] = "180s" + + if v, ok := cf["skipEmptyPrefix"]; ok { + rc.skipEmptyPrefix, _ = strconv.ParseBool(v) } + rc.key = cf["key"] rc.conninfo = cf["conn"] - rc.dbNum, _ = strconv.Atoi(cf["dbNum"]) rc.password = cf["password"] rc.maxIdle, _ = strconv.Atoi(cf["maxIdle"]) diff --git a/client/cache/redis/redis_test.go b/client/cache/redis/redis_test.go index 138ccc2c..b4ceee2e 100644 --- a/client/cache/redis/redis_test.go +++ b/client/cache/redis/redis_test.go @@ -248,3 +248,51 @@ func (m *MockOrm) Load(key string) (any, error) { } return m.kvs[key], nil } + +func TestCache_associate(t *testing.T) { + testCases := []struct { + name string + skipEmptyPrefix bool + prefix string + input string + wantRes string + }{ + { + name: "skip prefix", + skipEmptyPrefix: true, + prefix: "", + input: "my-key", + wantRes: "my-key", + }, + { + name: "skip prefix but prefix not empty", + skipEmptyPrefix: true, + prefix: "abc", + input: "my-key", + wantRes: "abc:my-key", + }, + { + name: "using empty prefix", + skipEmptyPrefix: false, + prefix: "", + input: "my-key", + wantRes: ":my-key", + }, + { + name: "using prefix", + prefix: "abc", + input: "my-key", + wantRes: "abc:my-key", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + c := NewRedisCache().(*Cache) + c.skipEmptyPrefix = tc.skipEmptyPrefix + c.key = tc.prefix + res := c.associate(tc.input) + assert.Equal(t, tc.wantRes, res) + }) + } +} diff --git a/client/cache/write_delete.go b/client/cache/write_delete.go index d7655fdc..a7ed3a1e 100644 --- a/client/cache/write_delete.go +++ b/client/cache/write_delete.go @@ -90,7 +90,7 @@ func (c *WriteDoubleDeleteCache) Set( }) err = c.Cache.Delete(ctx, key) if err != nil { - return berror.Wrap(err, DeleteFailed, fmt.Sprintf("key: %s", key)) + return berror.Wrap(err, DeleteFailed, fmt.Sprintf("write double delete pattern failed to delete the key: %s", key)) } return nil } diff --git a/client/orm/cmd_utils_test.go b/client/orm/cmd_utils_test.go index 38bcea4d..1ba42990 100644 --- a/client/orm/cmd_utils_test.go +++ b/client/orm/cmd_utils_test.go @@ -3,8 +3,9 @@ package orm import ( "testing" - "github.com/beego/beego/v2/client/orm/internal/models" "github.com/stretchr/testify/assert" + + "github.com/beego/beego/v2/client/orm/internal/models" ) func Test_getColumnTyp(t *testing.T) {