Skip to content

Commit

Permalink
feat: added Clear() method to flush all cache data
Browse files Browse the repository at this point in the history
  • Loading branch information
eko committed Oct 24, 2019
1 parent 16d5e61 commit 7847237
Show file tree
Hide file tree
Showing 32 changed files with 509 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ if err != nil {
value := cacheManager.Get("my-key")
cacheManager.Delete("my-key")
cacheManager.Clear() // Clears the entire cache, in case you want to flush all cache
```
#### Memory (using Bigcache)
Expand Down
5 changes: 5 additions & 0 deletions cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ func (c *Cache) Invalidate(options store.InvalidateOptions) error {
return c.codec.Invalidate(options)
}

// Clear resets all cache data
func (c *Cache) Clear() error {
return c.codec.Clear()
}

// GetCodec returns the current codec
func (c *Cache) GetCodec() codec.CodecInterface {
return c.codec
Expand Down
30 changes: 30 additions & 0 deletions cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,36 @@ func TestCacheInvalidateWhenError(t *testing.T) {
assert.Equal(t, expectedErr, err)
}

func TestCacheClear(t *testing.T) {
// Given
store := &mocksStore.StoreInterface{}
store.On("Clear").Return(nil)

cache := New(store)

// When
err := cache.Clear()

// Then
assert.Nil(t, err)
}

func TestCacheClearWhenError(t *testing.T) {
// Given
expectedErr := errors.New("Unexpected error during invalidation")

store := &mocksStore.StoreInterface{}
store.On("Clear").Return(expectedErr)

cache := New(store)

// When
err := cache.Clear()

// Then
assert.Equal(t, expectedErr, err)
}

func TestCacheDeleteWhenError(t *testing.T) {
// Given
expectedErr := errors.New("Unable to delete key")
Expand Down
9 changes: 9 additions & 0 deletions cache/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ func (c *ChainCache) Invalidate(options store.InvalidateOptions) error {
return nil
}

// Clear resets all cache data
func (c *ChainCache) Clear() error {
for _, cache := range c.caches {
cache.Clear()
}

return nil
}

// setUntil sets a value in available caches, eventually until a given cache layer
func (c *ChainCache) setUntil(key, object interface{}, until *string) {
for _, cache := range c.caches {
Expand Down
38 changes: 38 additions & 0 deletions cache/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,44 @@ func TestChainInvalidateWhenError(t *testing.T) {
assert.Nil(t, err)
}

func TestChainClear(t *testing.T) {
// Given
// Cache 1
cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Clear").Return(nil)

// Cache 2
cache2 := &mocksCache.SetterCacheInterface{}
cache2.On("Clear").Return(nil)

cache := NewChain(cache1, cache2)

// When
err := cache.Clear()

// Then
assert.Nil(t, err)
}

func TestChainClearWhenError(t *testing.T) {
// Given
// Cache 1
cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Clear").Return(errors.New("An unexpected error has occurred while invalidation data"))

// Cache 2
cache2 := &mocksCache.SetterCacheInterface{}
cache2.On("Clear").Return(nil)

cache := NewChain(cache1, cache2)

// When
err := cache.Clear()

// Then
assert.Nil(t, err)
}

func TestChainGetType(t *testing.T) {
// Given
cache1 := &mocksCache.SetterCacheInterface{}
Expand Down
1 change: 1 addition & 0 deletions cache/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type CacheInterface interface {
Set(key, object interface{}, options *store.Options) error
Delete(key interface{}) error
Invalidate(options store.InvalidateOptions) error
Clear() error
GetType() string
}

Expand Down
5 changes: 5 additions & 0 deletions cache/loadable.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ func (c *LoadableCache) Invalidate(options store.InvalidateOptions) error {
return c.cache.Invalidate(options)
}

// Clear resets all cache data
func (c *LoadableCache) Clear() error {
return c.cache.Clear()
}

// GetType returns the cache type
func (c *LoadableCache) GetType() string {
return LoadableType
Expand Down
38 changes: 38 additions & 0 deletions cache/loadable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,44 @@ func TestLoadableInvalidateWhenError(t *testing.T) {
assert.Equal(t, expectedErr, err)
}

func TestLoadableClear(t *testing.T) {
// Given
cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Clear").Return(nil)

loadFunc := func(key interface{}) (interface{}, error) {
return "a value", nil
}

cache := NewLoadable(loadFunc, cache1)

// When
err := cache.Clear()

// Then
assert.Nil(t, err)
}

func TestLoadableClearWhenError(t *testing.T) {
// Given
expectedErr := errors.New("Unexpected error when invalidating data")

cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Clear").Return(expectedErr)

loadFunc := func(key interface{}) (interface{}, error) {
return "a value", nil
}

cache := NewLoadable(loadFunc, cache1)

// When
err := cache.Clear()

// Then
assert.Equal(t, expectedErr, err)
}

func TestLoadableGetType(t *testing.T) {
// Given
cache1 := &mocksCache.SetterCacheInterface{}
Expand Down
5 changes: 5 additions & 0 deletions cache/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ func (c *MetricCache) Invalidate(options store.InvalidateOptions) error {
return c.cache.Invalidate(options)
}

// Clear resets all cache data
func (c *MetricCache) Clear() error {
return c.cache.Clear()
}

// Get obtains a value from cache and also records metrics
func (c *MetricCache) updateMetrics(cache CacheInterface) {
switch current := cache.(type) {
Expand Down
34 changes: 34 additions & 0 deletions cache/metric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,40 @@ func TestMetricInvalidateWhenError(t *testing.T) {
assert.Equal(t, expectedErr, err)
}

func TestMetricClear(t *testing.T) {
// Given
cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Clear").Return(nil)

metrics := &mocksMetrics.MetricsInterface{}

cache := NewMetric(metrics, cache1)

// When
err := cache.Clear()

// Then
assert.Nil(t, err)
}

func TestMetricClearWhenError(t *testing.T) {
// Given
expectedErr := errors.New("Unexpected error while clearing cache")

cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Clear").Return(expectedErr)

metrics := &mocksMetrics.MetricsInterface{}

cache := NewMetric(metrics, cache1)

// When
err := cache.Clear()

// Then
assert.Equal(t, expectedErr, err)
}

func TestMetricGetType(t *testing.T) {
// Given
cache1 := &mocksCache.SetterCacheInterface{}
Expand Down
15 changes: 15 additions & 0 deletions codec/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type Stats struct {
DeleteError int
InvalidateSuccess int
InvalidateError int
ClearSuccess int
ClearError int
}

// Codec represents an instance of a cache store
Expand Down Expand Up @@ -83,6 +85,19 @@ func (c *Codec) Invalidate(options store.InvalidateOptions) error {
return err
}

// Clear resets all codec store data
func (c *Codec) Clear() error {
err := c.store.Clear()

if err == nil {
c.stats.ClearSuccess++
} else {
c.stats.ClearError++
}

return err
}

// GetStore returns the store associated to this codec
func (c *Codec) GetStore() store.StoreInterface {
return c.store
Expand Down
68 changes: 68 additions & 0 deletions codec/codec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ func TestGetWhenHit(t *testing.T) {
assert.Equal(t, 0, codec.GetStats().DeleteError)
assert.Equal(t, 0, codec.GetStats().InvalidateSuccess)
assert.Equal(t, 0, codec.GetStats().InvalidateError)
assert.Equal(t, 0, codec.GetStats().ClearSuccess)
assert.Equal(t, 0, codec.GetStats().ClearError)
}

func TestGetWhenMiss(t *testing.T) {
Expand All @@ -75,6 +77,8 @@ func TestGetWhenMiss(t *testing.T) {
assert.Equal(t, 0, codec.GetStats().DeleteError)
assert.Equal(t, 0, codec.GetStats().InvalidateSuccess)
assert.Equal(t, 0, codec.GetStats().InvalidateError)
assert.Equal(t, 0, codec.GetStats().ClearSuccess)
assert.Equal(t, 0, codec.GetStats().ClearError)
}

func TestSetWhenSuccess(t *testing.T) {
Expand Down Expand Up @@ -108,6 +112,8 @@ func TestSetWhenSuccess(t *testing.T) {
assert.Equal(t, 0, codec.GetStats().DeleteError)
assert.Equal(t, 0, codec.GetStats().InvalidateSuccess)
assert.Equal(t, 0, codec.GetStats().InvalidateError)
assert.Equal(t, 0, codec.GetStats().ClearSuccess)
assert.Equal(t, 0, codec.GetStats().ClearError)
}

func TestSetWhenError(t *testing.T) {
Expand Down Expand Up @@ -143,6 +149,8 @@ func TestSetWhenError(t *testing.T) {
assert.Equal(t, 0, codec.GetStats().DeleteError)
assert.Equal(t, 0, codec.GetStats().InvalidateSuccess)
assert.Equal(t, 0, codec.GetStats().InvalidateError)
assert.Equal(t, 0, codec.GetStats().ClearSuccess)
assert.Equal(t, 0, codec.GetStats().ClearError)
}

func TestDeleteWhenSuccess(t *testing.T) {
Expand All @@ -166,6 +174,8 @@ func TestDeleteWhenSuccess(t *testing.T) {
assert.Equal(t, 0, codec.GetStats().DeleteError)
assert.Equal(t, 0, codec.GetStats().InvalidateSuccess)
assert.Equal(t, 0, codec.GetStats().InvalidateError)
assert.Equal(t, 0, codec.GetStats().ClearSuccess)
assert.Equal(t, 0, codec.GetStats().ClearError)
}

func TesDeleteWhenError(t *testing.T) {
Expand All @@ -191,6 +201,8 @@ func TesDeleteWhenError(t *testing.T) {
assert.Equal(t, 1, codec.GetStats().DeleteError)
assert.Equal(t, 0, codec.GetStats().InvalidateSuccess)
assert.Equal(t, 0, codec.GetStats().InvalidateError)
assert.Equal(t, 0, codec.GetStats().ClearSuccess)
assert.Equal(t, 0, codec.GetStats().ClearError)
}

func TestInvalidateWhenSuccess(t *testing.T) {
Expand Down Expand Up @@ -218,6 +230,8 @@ func TestInvalidateWhenSuccess(t *testing.T) {
assert.Equal(t, 0, codec.GetStats().DeleteError)
assert.Equal(t, 1, codec.GetStats().InvalidateSuccess)
assert.Equal(t, 0, codec.GetStats().InvalidateError)
assert.Equal(t, 0, codec.GetStats().ClearSuccess)
assert.Equal(t, 0, codec.GetStats().ClearError)
}

func TestInvalidateWhenError(t *testing.T) {
Expand Down Expand Up @@ -247,6 +261,60 @@ func TestInvalidateWhenError(t *testing.T) {
assert.Equal(t, 0, codec.GetStats().DeleteError)
assert.Equal(t, 0, codec.GetStats().InvalidateSuccess)
assert.Equal(t, 1, codec.GetStats().InvalidateError)
assert.Equal(t, 0, codec.GetStats().ClearSuccess)
assert.Equal(t, 0, codec.GetStats().ClearError)
}

func TestClearWhenSuccess(t *testing.T) {
// Given
store := &mocksStore.StoreInterface{}
store.On("Clear").Return(nil)

codec := New(store)

// When
err := codec.Clear()

// Then
assert.Nil(t, err)

assert.Equal(t, 0, codec.GetStats().Hits)
assert.Equal(t, 0, codec.GetStats().Miss)
assert.Equal(t, 0, codec.GetStats().SetSuccess)
assert.Equal(t, 0, codec.GetStats().SetError)
assert.Equal(t, 0, codec.GetStats().DeleteSuccess)
assert.Equal(t, 0, codec.GetStats().DeleteError)
assert.Equal(t, 0, codec.GetStats().InvalidateSuccess)
assert.Equal(t, 0, codec.GetStats().InvalidateError)
assert.Equal(t, 1, codec.GetStats().ClearSuccess)
assert.Equal(t, 0, codec.GetStats().ClearError)
}

func TestClearWhenError(t *testing.T) {
// Given
expectedErr := errors.New("Unexpected error when clearing cache")

store := &mocksStore.StoreInterface{}
store.On("Clear").Return(expectedErr)

codec := New(store)

// When
err := codec.Clear()

// Then
assert.Equal(t, expectedErr, err)

assert.Equal(t, 0, codec.GetStats().Hits)
assert.Equal(t, 0, codec.GetStats().Miss)
assert.Equal(t, 0, codec.GetStats().SetSuccess)
assert.Equal(t, 0, codec.GetStats().SetError)
assert.Equal(t, 0, codec.GetStats().DeleteSuccess)
assert.Equal(t, 0, codec.GetStats().DeleteError)
assert.Equal(t, 0, codec.GetStats().InvalidateSuccess)
assert.Equal(t, 0, codec.GetStats().InvalidateError)
assert.Equal(t, 0, codec.GetStats().ClearSuccess)
assert.Equal(t, 1, codec.GetStats().ClearError)
}

func TestGetStore(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions codec/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type CodecInterface interface {
Set(key interface{}, value interface{}, options *store.Options) error
Delete(key interface{}) error
Invalidate(options store.InvalidateOptions) error
Clear() error

GetStore() store.StoreInterface
GetStats() *Stats
Expand Down
Loading

0 comments on commit 7847237

Please sign in to comment.