Skip to content

Commit

Permalink
Merge pull request #44 from Han-Ya-Jun/feat-fix-fallback-config
Browse files Browse the repository at this point in the history
feat: add cache options
  • Loading branch information
Han-Ya-Jun committed Jul 30, 2024
2 parents d3dc33d + aeaee1f commit 45a30da
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 23 deletions.
54 changes: 40 additions & 14 deletions cache/memory/base_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,46 @@ import (

const EmptyCacheExpiration = 5 * time.Second

// NewBaseCache creates a new baseCache instance which implements Cache interface.
func NewBaseCache(disabled bool, retrieveFunc RetrieveFunc, backend backend.Backend) Cache {
return &BaseCache{
backend: backend,
disabled: disabled,
retrieveFunc: retrieveFunc,
}
}

// BaseCache is a cache which retrieves data from the backend and stores it in the cache.
type BaseCache struct {
backend backend.Backend

disabled bool
retrieveFunc RetrieveFunc
g singleflight.Group
disabled bool
retrieveFunc RetrieveFunc
g singleflight.Group
withEmptyCache bool
emptyCacheExpireDuration time.Duration
}

type Option func(*BaseCache)

func WithNoCache() Option {
return func(cache *BaseCache) {
cache.disabled = true
}
}

// WithEmptyCache will set the key EmptyCache if retrieve fail from retrieveFunc
func WithEmptyCache(timeout time.Duration) Option {
return func(cache *BaseCache) {
if timeout == 0 {
timeout = EmptyCacheExpiration
}
cache.withEmptyCache = true
cache.emptyCacheExpireDuration = timeout
}
}

// NewBaseCache creates a new baseCache instance which implements Cache interface.
func NewBaseCache(retrieveFunc RetrieveFunc, backend backend.Backend, options ...Option) Cache {
c := &BaseCache{
backend: backend,
retrieveFunc: retrieveFunc,
}
for _, o := range options {
o(c)
}
return c
}

// EmptyCache is a placeholder for the missing key
Expand Down Expand Up @@ -91,8 +115,10 @@ func (c *BaseCache) doRetrieve(ctx context.Context, k cache.Key) (interface{}, e
})

if err != nil {
// ! if error, cache it too, make it short enough(5s)
c.backend.Set(key, EmptyCache{err: err}, EmptyCacheExpiration)
if c.withEmptyCache {
// ! if error, cache it too, make it short enough(5s)
c.backend.Set(key, EmptyCache{err: err}, c.emptyCacheExpireDuration)
}
return nil, err
}

Expand Down
6 changes: 3 additions & 3 deletions cache/memory/base_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ var _ = Describe("BaseCache", func() {
expiration := 5 * time.Minute
be = backend.NewMemoryBackend("test", expiration, nil)

c = NewBaseCache(false, retrieveTest, be)
c = NewBaseCache(retrieveTest, be, WithEmptyCache(0))
ctx = context.Background()
})

Expand Down Expand Up @@ -105,7 +105,7 @@ var _ = Describe("BaseCache", func() {
})

It("Disabled then get", func() {
c = NewBaseCache(true, retrieveTest, be)
c = NewBaseCache(retrieveTest, be, WithNoCache())

aKey := cache.NewStringKey("a")
x, err := c.Get(ctx, aKey)
Expand Down Expand Up @@ -378,7 +378,7 @@ var _ = Describe("BaseCache", func() {
})

It("retrieveError", func() {
c = NewBaseCache(true, retrieveError, be)
c = NewBaseCache(retrieveError, be, WithNoCache())
assert.NotNil(GinkgoT(), c)
aKey := cache.NewStringKey("a")
_, err := c.Get(ctx, aKey)
Expand Down
10 changes: 6 additions & 4 deletions cache/memory/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,26 @@ import (

// NewCache creates a new cache object.
// - name: the cache name.
// - disabled: whether the cache is disabled.
// - retrieveFunc: the function to retrieve the real data.
// - expiration: the expiration time.
// - randomExtraExpirationFunc: the function to generate a random duration, used to add extra expiration for each key.
// - options: the options for the cache . eg:
// WithNoCache:disable cache
// WithEmptyCache(duration): set the key EmptyCache if retrieve fail from retrieveFunc
func NewCache(
name string,
disabled bool,
retrieveFunc RetrieveFunc,
expiration time.Duration,
randomExtraExpirationFunc backend.RandomExtraExpirationDurationFunc,
options ...Option,
) Cache {
be := backend.NewMemoryBackend(name, expiration, randomExtraExpirationFunc)
return NewBaseCache(disabled, retrieveFunc, be)
return NewBaseCache(retrieveFunc, be, options...)
}

// NewMockCache create a memory cache for mock
func NewMockCache(retrieveFunc RetrieveFunc) Cache {
be := backend.NewMemoryBackend("mockCache", 5*time.Minute, nil)

return NewBaseCache(false, retrieveFunc, be)
return NewBaseCache(retrieveFunc, be)
}
30 changes: 28 additions & 2 deletions cache/memory/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ package memory

import (
"context"
"errors"
"time"

. "github.com/onsi/ginkgo/v2"
Expand All @@ -21,20 +22,45 @@ import (
"github.com/TencentBlueKing/gopkg/cache"
)

var cacheError = errors.New("cache error")

func retrieveOK(ctx context.Context, k cache.Key) (interface{}, error) {
return "ok", nil
return "", nil
}

func retrieveErr(ctx context.Context, k cache.Key) (interface{}, error) {
return nil, cacheError
}

var _ = Describe("Cache", func() {

var ctx context.Context

It("New", func() {
expiration := 5 * time.Minute

c := NewCache("test", false, retrieveOK, expiration, nil)
c := NewCache("test", retrieveOK, expiration, nil)
assert.NotNil(GinkgoT(), c)
})

It("NewMock", func() {
c := NewMockCache(retrieveOK)
assert.NotNil(GinkgoT(), c)
})

It("Cache Disable", func() {
expiration := 5 * time.Minute
c := NewCache("test", retrieveOK, expiration, nil, WithNoCache())
assert.True(GinkgoT(), c.Disabled())
})

It("Cache WithEmptyCache", func() {
aKey := cache.NewStringKey("test")
expiration := 5 * time.Minute
c := NewCache("test", retrieveErr, expiration, nil, WithEmptyCache(0))
_, err := c.Get(ctx, aKey)
assert.ErrorIs(GinkgoT(), err, cacheError)

})

})

0 comments on commit 45a30da

Please sign in to comment.