cache: fix typo and optimize the naming
This commit is contained in:
parent
e420ad0546
commit
2e3b131525
@ -10,6 +10,7 @@
|
||||
- [Fix 4435: Controller SaveToFile remove all temp file](https://github.com/beego/beego/pull/5138)
|
||||
- [Fix 5079: Split signalChan into flushChan and closeChan](https://github.com/beego/beego/pull/5139)
|
||||
- [Fix 5172: protect field access with lock to avoid possible data race](https://github.com/beego/beego/pull/5210)
|
||||
- [cache: fix typo and optimize the naming]()
|
||||
|
||||
# v2.0.7
|
||||
- [Upgrade github.com/go-kit/kit, CVE-2022-24450](https://github.com/beego/beego/pull/5121)
|
||||
|
||||
8
client/cache/bloom_filter_cache.go
vendored
8
client/cache/bloom_filter_cache.go
vendored
@ -24,7 +24,7 @@ import (
|
||||
|
||||
type BloomFilterCache struct {
|
||||
Cache
|
||||
BloomFilter
|
||||
blm BloomFilter
|
||||
loadFunc func(ctx context.Context, key string) (any, error)
|
||||
expiration time.Duration // set cache expiration, default never expire
|
||||
}
|
||||
@ -34,7 +34,7 @@ type BloomFilter interface {
|
||||
Add(data string)
|
||||
}
|
||||
|
||||
func NewBloomFilterCache(cache Cache, ln func(context.Context, string) (any, error), blm BloomFilter,
|
||||
func NewBloomFilterCache(cache Cache, ln func(ctx context.Context, key string) (any, error), blm BloomFilter,
|
||||
expiration time.Duration,
|
||||
) (*BloomFilterCache, error) {
|
||||
if cache == nil || ln == nil || blm == nil {
|
||||
@ -43,7 +43,7 @@ func NewBloomFilterCache(cache Cache, ln func(context.Context, string) (any, err
|
||||
|
||||
return &BloomFilterCache{
|
||||
Cache: cache,
|
||||
BloomFilter: blm,
|
||||
blm: blm,
|
||||
loadFunc: ln,
|
||||
expiration: expiration,
|
||||
}, nil
|
||||
@ -55,7 +55,7 @@ func (bfc *BloomFilterCache) Get(ctx context.Context, key string) (any, error) {
|
||||
return nil, err
|
||||
}
|
||||
if errors.Is(err, ErrKeyNotExist) {
|
||||
exist := bfc.BloomFilter.Test(key)
|
||||
exist := bfc.blm.Test(key)
|
||||
if exist {
|
||||
val, err = bfc.loadFunc(ctx, key)
|
||||
if err != nil {
|
||||
|
||||
55
client/cache/bloom_filter_cache_test.go
vendored
55
client/cache/bloom_filter_cache_test.go
vendored
@ -18,6 +18,7 @@ package cache
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@ -175,29 +176,31 @@ func TestBloomFilterCache_Get(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// This implementation of Bloom filters cache is NOT safe for concurrent use.
|
||||
// Uncomment the following method.
|
||||
// func TestBloomFilterCache_Get_Concurrency(t *testing.T) {
|
||||
// bfc, err := NewBloomFilterCache(cacheUnderlying, loadFunc, mockBloom, time.Minute)
|
||||
// assert.Nil(t, err)
|
||||
//
|
||||
// _ = mockDB.Db.ClearAll(context.Background())
|
||||
// _ = mockDB.Db.Put(context.Background(), "key_11", "value_11", 0)
|
||||
// mockBloom.AddString("key_11")
|
||||
//
|
||||
// var wg sync.WaitGroup
|
||||
// wg.Add(100000)
|
||||
// for i := 0; i < 100000; i++ {
|
||||
// key := fmt.Sprintf("key_%d", i)
|
||||
// go func(key string) {
|
||||
// defer wg.Done()
|
||||
// val, _ := bfc.Get(context.Background(), key)
|
||||
//
|
||||
// if val != nil {
|
||||
// assert.Equal(t, "value_11", val)
|
||||
// }
|
||||
// }(key)
|
||||
// }
|
||||
// wg.Wait()
|
||||
// assert.Equal(t, int64(1), mockDB.loadCnt)
|
||||
// }
|
||||
func ExampleNewBloomFilterCache() {
|
||||
c := NewMemoryCache()
|
||||
c, err := NewBloomFilterCache(c, func(ctx context.Context, key string) (any, error) {
|
||||
return fmt.Sprintf("hello, %s", key), nil
|
||||
}, &AlwaysExist{}, time.Minute)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
val, err := c.Get(context.Background(), "Beego")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(val)
|
||||
// Output:
|
||||
// hello, Beego
|
||||
}
|
||||
|
||||
type AlwaysExist struct {
|
||||
}
|
||||
|
||||
func (*AlwaysExist) Test(string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (*AlwaysExist) Add(string) {
|
||||
|
||||
}
|
||||
|
||||
4
client/cache/random_expired_cache.go
vendored
4
client/cache/random_expired_cache.go
vendored
@ -24,8 +24,8 @@ import (
|
||||
// RandomExpireCacheOption implement genreate random time offset expired option
|
||||
type RandomExpireCacheOption func(*RandomExpireCache)
|
||||
|
||||
// WithOffsetFunc returns a RandomExpireCacheOption that configures the offset function
|
||||
func WithOffsetFunc(fn func() time.Duration) RandomExpireCacheOption {
|
||||
// WithRandomExpireOffsetFunc returns a RandomExpireCacheOption that configures the offset function
|
||||
func WithRandomExpireOffsetFunc(fn func() time.Duration) RandomExpireCacheOption {
|
||||
return func(cache *RandomExpireCache) {
|
||||
cache.offset = fn
|
||||
}
|
||||
|
||||
33
client/cache/random_expired_cache_test.go
vendored
33
client/cache/random_expired_cache_test.go
vendored
@ -16,6 +16,7 @@ package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -86,14 +87,42 @@ func TestRandomExpireCache(t *testing.T) {
|
||||
assert.True(t, strings.Contains(err.Error(), "key isn't exist"))
|
||||
}
|
||||
|
||||
func TestWithOffsetFunc(t *testing.T) {
|
||||
func TestWithRandomExpireOffsetFunc(t *testing.T) {
|
||||
bm, err := NewCache("memory", `{"interval":20}`)
|
||||
assert.Nil(t, err)
|
||||
|
||||
magic := -time.Duration(rand.Int())
|
||||
cache := NewRandomExpireCache(bm, WithOffsetFunc(func() time.Duration {
|
||||
cache := NewRandomExpireCache(bm, WithRandomExpireOffsetFunc(func() time.Duration {
|
||||
return magic
|
||||
}))
|
||||
// offset should return the magic value
|
||||
assert.Equal(t, magic, cache.(*RandomExpireCache).offset())
|
||||
}
|
||||
|
||||
func ExampleNewRandomExpireCache() {
|
||||
mc := NewMemoryCache()
|
||||
// use the default strategy which will generate random time offset (range: [3s,8s)) expired
|
||||
c := NewRandomExpireCache(mc)
|
||||
// so the expiration will be [1m3s, 1m8s)
|
||||
err := c.Put(context.Background(), "hello", "world", time.Minute)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c = NewRandomExpireCache(mc,
|
||||
// based on the expiration
|
||||
WithRandomExpireOffsetFunc(func() time.Duration {
|
||||
val := rand.Int31n(100)
|
||||
fmt.Printf("calculate offset")
|
||||
return time.Duration(val) * time.Second
|
||||
}))
|
||||
|
||||
// so the expiration will be [1m0s, 1m100s)
|
||||
err = c.Put(context.Background(), "hello", "world", time.Minute)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// calculate offset
|
||||
}
|
||||
|
||||
26
client/cache/read_through_test.go
vendored
26
client/cache/read_through_test.go
vendored
@ -17,6 +17,7 @@ package cache
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -143,3 +144,28 @@ func (m *MockOrm) Load(key string) (any, error) {
|
||||
}
|
||||
return m.kvs[key], nil
|
||||
}
|
||||
|
||||
func ExampleNewReadThroughCache() {
|
||||
c := NewMemoryCache()
|
||||
var err error
|
||||
c, err = NewReadThroughCache(c,
|
||||
// expiration, same as the expiration of key
|
||||
time.Minute,
|
||||
// load func, how to load data if the key is absent.
|
||||
// in general, you should load data from database.
|
||||
func(ctx context.Context, key string) (any, error) {
|
||||
return fmt.Sprintf("hello, %s", key), nil
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
val, err := c.Get(context.Background(), "Beego")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Print(val)
|
||||
|
||||
// Output:
|
||||
// hello, Beego
|
||||
}
|
||||
|
||||
18
client/cache/singleflight_test.go
vendored
18
client/cache/singleflight_test.go
vendored
@ -16,6 +16,7 @@ package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@ -70,3 +71,20 @@ func testSingleflightCacheConcurrencyGet(t *testing.T, bm Cache) {
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func ExampleNewSingleflightCache() {
|
||||
c := NewMemoryCache()
|
||||
c, err := NewSingleflightCache(c, time.Minute, func(ctx context.Context, key string) (any, error) {
|
||||
return fmt.Sprintf("hello, %s", key), nil
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
val, err := c.Get(context.Background(), "Beego")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Print(val)
|
||||
// Output:
|
||||
// hello, Beego
|
||||
}
|
||||
|
||||
10
client/cache/write_through.go
vendored
10
client/cache/write_through.go
vendored
@ -22,24 +22,26 @@ import (
|
||||
"github.com/beego/beego/v2/core/berror"
|
||||
)
|
||||
|
||||
type WriteThoughCache struct {
|
||||
type WriteThroughCache struct {
|
||||
Cache
|
||||
storeFunc func(ctx context.Context, key string, val any) error
|
||||
}
|
||||
|
||||
func NewWriteThoughCache(cache Cache, fn func(ctx context.Context, key string, val any) error) (*WriteThoughCache, error) {
|
||||
// NewWriteThroughCache creates a write through cache pattern decorator.
|
||||
// The fn is the function that persistent the key and val.
|
||||
func NewWriteThroughCache(cache Cache, fn func(ctx context.Context, key string, val any) error) (*WriteThroughCache, error) {
|
||||
if fn == nil || cache == nil {
|
||||
return nil, berror.Error(InvalidInitParameters, "cache or storeFunc can not be nil")
|
||||
}
|
||||
|
||||
w := &WriteThoughCache{
|
||||
w := &WriteThroughCache{
|
||||
Cache: cache,
|
||||
storeFunc: fn,
|
||||
}
|
||||
return w, nil
|
||||
}
|
||||
|
||||
func (w *WriteThoughCache) Set(ctx context.Context, key string, val any, expiration time.Duration) error {
|
||||
func (w *WriteThroughCache) Set(ctx context.Context, key string, val any, expiration time.Duration) error {
|
||||
err := w.storeFunc(ctx, key, val)
|
||||
if err != nil {
|
||||
return berror.Wrap(err, PersistCacheFailed, fmt.Sprintf("key: %s, val: %v", key, val))
|
||||
|
||||
26
client/cache/write_through_test.go
vendored
26
client/cache/write_through_test.go
vendored
@ -60,7 +60,7 @@ func TestWriteThoughCache_Set(t *testing.T) {
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
w, err := NewWriteThoughCache(tt.cache, tt.storeFunc)
|
||||
w, err := NewWriteThroughCache(tt.cache, tt.storeFunc)
|
||||
if err != nil {
|
||||
assert.EqualError(t, tt.wantErr, err.Error())
|
||||
return
|
||||
@ -94,7 +94,7 @@ func TestNewWriteThoughCache(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantRes *WriteThoughCache
|
||||
wantRes *WriteThroughCache
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
@ -119,7 +119,7 @@ func TestNewWriteThoughCache(t *testing.T) {
|
||||
cache: underlyingCache,
|
||||
fn: storeFunc,
|
||||
},
|
||||
wantRes: &WriteThoughCache{
|
||||
wantRes: &WriteThroughCache{
|
||||
Cache: underlyingCache,
|
||||
storeFunc: storeFunc,
|
||||
},
|
||||
@ -127,7 +127,7 @@ func TestNewWriteThoughCache(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := NewWriteThoughCache(tt.args.cache, tt.args.fn)
|
||||
_, err := NewWriteThroughCache(tt.args.cache, tt.args.fn)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
if err != nil {
|
||||
return
|
||||
@ -135,3 +135,21 @@ func TestNewWriteThoughCache(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleNewWriteThroughCache() {
|
||||
c := NewMemoryCache()
|
||||
wtc, err := NewWriteThroughCache(c, func(ctx context.Context, key string, val any) error {
|
||||
fmt.Printf("write data to somewhere key %s, val %v \n", key, val)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = wtc.Set(context.Background(),
|
||||
"/biz/user/id=1", "I am user 1", time.Minute)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Output:
|
||||
// write data to somewhere key /biz/user/id=1, val I am user 1
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user