Merge pull request #5001 from ktalg/develop

fix: nil offset function of RandomExpireCache instance
This commit is contained in:
Ming Deng 2022-06-29 21:19:39 +08:00 committed by GitHub
commit 3eb35c710c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 10 deletions

View File

@ -17,12 +17,20 @@ package cache
import (
"context"
"math/rand"
"sync/atomic"
"time"
)
// 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 {
return func(cache *RandomExpireCache) {
cache.offset = fn
}
}
// RandomExpireCache prevent cache batch invalidation
// Cache random time offset expired
type RandomExpireCache struct {
@ -38,15 +46,30 @@ func (rec *RandomExpireCache) Put(ctx context.Context, key string, val interface
// NewRandomExpireCache return random expire cache struct
func NewRandomExpireCache(adapter Cache, opts ...RandomExpireCacheOption) Cache {
var rec RandomExpireCache
rec.Cache = adapter
rec := RandomExpireCache{
Cache: adapter,
offset: defaultExpiredFunc(),
}
for _, fn := range opts {
fn(&rec)
}
return &rec
}
// defaultExpiredFunc genreate random time offset expired
func defaultExpiredFunc() time.Duration {
return time.Duration(rand.Intn(5)+3) * time.Second
// defaultExpiredFunc return a func that used to generate random time offset (range: [3s,8s)) expired
func defaultExpiredFunc() func() time.Duration {
const size = 5
var randTimes [size]time.Duration
for i := range randTimes {
randTimes[i] = time.Duration(i+3) * time.Second
}
// shuffle values
for i := range randTimes {
n := rand.Intn(size)
randTimes[i], randTimes[n] = randTimes[n], randTimes[i]
}
var i uint64
return func() time.Duration {
return randTimes[atomic.AddUint64(&i, 1)%size]
}
}

View File

@ -16,6 +16,7 @@ package cache
import (
"context"
"math/rand"
"strings"
"testing"
"time"
@ -27,10 +28,9 @@ func TestRandomExpireCache(t *testing.T) {
bm, err := NewCache("memory", `{"interval":20}`)
assert.Nil(t, err)
// cache := NewRandomExpireCache(bm)
cache := NewRandomExpireCache(bm, func(opt *RandomExpireCache) {
opt.offset = defaultExpiredFunc
})
cache := NewRandomExpireCache(bm)
// should not be nil
assert.NotNil(t, cache.(*RandomExpireCache).offset)
timeoutDuration := 3 * time.Second
@ -84,5 +84,16 @@ func TestRandomExpireCache(t *testing.T) {
assert.NotNil(t, err)
assert.True(t, strings.Contains(err.Error(), "key isn't exist"))
}
func TestWithOffsetFunc(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 {
return magic
}))
// offset should return the magic value
assert.Equal(t, magic, cache.(*RandomExpireCache).offset())
}