cache/redis: support skipEmptyPrefix option (#5264)

This commit is contained in:
Ming Deng 2023-06-26 13:41:08 +08:00 committed by GitHub
parent ec884b96b1
commit 1047faadfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 68 additions and 11 deletions

View File

@ -6,6 +6,7 @@
- [fix 5255: Check the rows.Err() if rows.Next() is false](https://github.com/beego/beego/pull/5256) - [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) - [orm: missing handling %COL% placeholder](https://github.com/beego/beego/pull/5257)
- [fix: use of ioutil package](https://github.com/beego/beego/pull/5261) - [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 ## ORM refactoring
- [introducing internal/models pkg](https://github.com/beego/beego/pull/5238) - [introducing internal/models pkg](https://github.com/beego/beego/pull/5238)

View File

@ -51,10 +51,16 @@ type Cache struct {
p *redis.Pool // redis connection pool p *redis.Pool // redis connection pool
conninfo string conninfo string
dbNum int dbNum int
// key actually is prefix.
key string key string
password string password string
maxIdle int 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 value (less than the redis server's timeout value)
timeout time.Duration timeout time.Duration
} }
@ -83,6 +89,9 @@ func (rc *Cache) do(commandName string, args ...interface{}) (interface{}, error
// associate with config key. // associate with config key.
func (rc *Cache) associate(originKey interface{}) string { 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) 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. // 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 // Cached items in redis are stored forever, no garbage collection happens
func (rc *Cache) StartAndGC(config string) error { func (rc *Cache) StartAndGC(config string) error {
var cf map[string]string var cf map[string]string
@ -215,21 +224,19 @@ func (rc *Cache) StartAndGC(config string) error {
cf["conn"] = cf["conn"][i+1:] cf["conn"] = cf["conn"][i+1:]
} }
if _, ok := cf["dbNum"]; !ok { if v, ok := cf["dbNum"]; ok {
cf["dbNum"] = "0" rc.dbNum, _ = strconv.Atoi(v)
}
if _, ok := cf["password"]; !ok {
cf["password"] = ""
} }
if _, ok := cf["maxIdle"]; !ok { if _, ok := cf["maxIdle"]; !ok {
cf["maxIdle"] = "3" 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.key = cf["key"]
rc.conninfo = cf["conn"] rc.conninfo = cf["conn"]
rc.dbNum, _ = strconv.Atoi(cf["dbNum"])
rc.password = cf["password"] rc.password = cf["password"]
rc.maxIdle, _ = strconv.Atoi(cf["maxIdle"]) rc.maxIdle, _ = strconv.Atoi(cf["maxIdle"])

View File

@ -248,3 +248,51 @@ func (m *MockOrm) Load(key string) (any, error) {
} }
return m.kvs[key], nil 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)
})
}
}

View File

@ -90,7 +90,7 @@ func (c *WriteDoubleDeleteCache) Set(
}) })
err = c.Cache.Delete(ctx, key) err = c.Cache.Delete(ctx, key)
if err != nil { 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 return nil
} }

View File

@ -3,8 +3,9 @@ package orm
import ( import (
"testing" "testing"
"github.com/beego/beego/v2/client/orm/internal/models"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/beego/beego/v2/client/orm/internal/models"
) )
func Test_getColumnTyp(t *testing.T) { func Test_getColumnTyp(t *testing.T) {