Skip to content

Commit

Permalink
feat: added cache & store delete() method
Browse files Browse the repository at this point in the history
  • Loading branch information
eko committed Oct 16, 2019
1 parent bd0c5fb commit 238e4ef
Show file tree
Hide file tree
Showing 34 changed files with 562 additions and 30 deletions.
20 changes: 14 additions & 6 deletions README.md
Expand Up @@ -56,6 +56,8 @@ if err != nil {
}
value := cacheManager.Get("my-key")
cacheManager.Delete("my-key")
```
#### Memory (using Bigcache)
Expand Down Expand Up @@ -93,6 +95,8 @@ if err != nil {
}
value := cacheManager.Get("my-key")
cacheManager.Delete("my-key")
```
#### Redis
Expand Down Expand Up @@ -202,22 +206,24 @@ cacheManager := cache.NewMetric(
)
// Initializes marshaler
marshaller := marshaler.New(cacheManager)
marshal := marshaler.New(cacheManager)
key := BookQuery{Slug: "my-test-amazing-book"}
value := Book{ID: 1, Name: "My test amazing book", Slug: "my-test-amazing-book"}
err = marshaller.Set(key, value)
err = marshal.Set(key, value)
if err != nil {
panic(err)
}
returnedValue, err := marshaller.Get(key, new(Book))
returnedValue, err := marshal.Get(key, new(Book))
if err != nil {
panic(err)
}
// Then, do what you want with the value
marshal.Delete("my-key")
```
The only thing you have to do is to specify the struct in which you want your value to be unmarshalled as a second argument when calling the `.Get()` method.
Expand Down Expand Up @@ -283,22 +289,24 @@ func main() {
),
))
marshaller := marshaler.New(cacheManager)
marshal := marshaler.New(cacheManager)
key := Book{Slug: "my-test-amazing-book"}
value := Book{ID: 1, Name: "My test amazing book", Slug: "my-test-amazing-book"}
err = marshaller.Set(key, value, nil)
err = marshal.Set(key, value, nil)
if err != nil {
panic(err)
}
returnedValue, err := marshaller.Get(key, new(Book))
returnedValue, err := marshal.Get(key, new(Book))
if err != nil {
panic(err)
}
fmt.Printf("%v\n", returnedValue)
marshal.Delete(key)
}
```
Expand Down
10 changes: 8 additions & 2 deletions cache/cache.go
Expand Up @@ -13,13 +13,13 @@ const (

// Cache represents the configuration needed by a cache
type Cache struct {
codec codec.CodecInterface
codec codec.CodecInterface
}

// New instanciates a new cache entry
func New(store store.StoreInterface) *Cache {
return &Cache{
codec: codec.New(store),
codec: codec.New(store),
}
}

Expand All @@ -35,6 +35,12 @@ func (c *Cache) Set(key, object interface{}, options *store.Options) error {
return c.codec.Set(cacheKey, object, options)
}

// Delete removes the cache item using the given key
func (c *Cache) Delete(key interface{}) error {
cacheKey := c.getCacheKey(key)
return c.codec.Delete(cacheKey)
}

// 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
Expand Up @@ -135,3 +135,33 @@ func TestCacheGetType(t *testing.T) {
// When - Then
assert.Equal(t, CacheType, cache.GetType())
}

func TestCacheDelete(t *testing.T) {
// Given
store := &mocksStore.StoreInterface{}
store.On("Delete", "9b1ac8a6e8ca8ca9477c0a252eb37756").Return(nil)

cache := New(store)

// When
err := cache.Delete("my-key")

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

func TestCacheDeleteWhenError(t *testing.T) {
// Given
expectedErr := errors.New("Unable to delete key")

store := &mocksStore.StoreInterface{}
store.On("Delete", "9b1ac8a6e8ca8ca9477c0a252eb37756").Return(expectedErr)

cache := New(store)

// When
err := cache.Delete("my-key")

// Then
assert.Equal(t, expectedErr, err)
}
9 changes: 9 additions & 0 deletions cache/chain.go
Expand Up @@ -56,6 +56,15 @@ func (c *ChainCache) Set(key, object interface{}, options *store.Options) error
return nil
}

// Delete removes a value from all available caches
func (c *ChainCache) Delete(key interface{}) error {
for _, cache := range c.caches {
cache.Delete(key)
}

return nil
}

// setUntil sets a value in available caches, eventually until a given cache layer
func (c *ChainCache) setUntil(key, object interface{}, until *string) error {
for _, cache := range c.caches {
Expand Down
38 changes: 38 additions & 0 deletions cache/chain_test.go
Expand Up @@ -118,6 +118,44 @@ func TestChainGetWhenAvailableInSecondCache(t *testing.T) {
assert.Equal(t, cacheValue, value)
}

func TestChainDelete(t *testing.T) {
// Given
// Cache 1
cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Delete", "my-key").Return(nil)

// Cache 2
cache2 := &mocksCache.SetterCacheInterface{}
cache2.On("Delete", "my-key").Return(nil)

cache := NewChain(cache1, cache2)

// When
err := cache.Delete("my-key")

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

func TestChainDeleteWhenError(t *testing.T) {
// Given
// Cache 1
cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Delete", "my-key").Return(errors.New("An error has occured while deleting key"))

// Cache 2
cache2 := &mocksCache.SetterCacheInterface{}
cache2.On("Delete", "my-key").Return(nil)

cache := NewChain(cache1, cache2)

// When
err := cache.Delete("my-key")

// 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
Expand Up @@ -9,6 +9,7 @@ import (
type CacheInterface interface {
Get(key interface{}) (interface{}, error)
Set(key, object interface{}, options *store.Options) error
Delete(key interface{}) error
GetType() string
}

Expand Down
6 changes: 6 additions & 0 deletions cache/loadable.go
Expand Up @@ -2,6 +2,7 @@ package cache

import (
"log"

"github.com/eko/gocache/store"
)

Expand Down Expand Up @@ -52,6 +53,11 @@ func (c *LoadableCache) Set(key, object interface{}, options *store.Options) err
return c.cache.Set(key, object, options)
}

// Delete removes a value from cache
func (c *LoadableCache) Delete(key interface{}) error {
return c.cache.Delete(key)
}

// GetType returns the cache type
func (c *LoadableCache) GetType() string {
return LoadableType
Expand Down
38 changes: 38 additions & 0 deletions cache/loadable_test.go
Expand Up @@ -90,6 +90,44 @@ func TestLoadableGetWhenAvailableInLoadFunc(t *testing.T) {
assert.Equal(t, cacheValue, value)
}

func TestLoadableDelete(t *testing.T) {
// Given
cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Delete", "my-key").Return(nil)

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

cache := NewLoadable(loadFunc, cache1)

// When
err := cache.Delete("my-key")

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

func TestLoadableDeleteWhenError(t *testing.T) {
// Given
expectedErr := errors.New("Unable to delete key")

cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Delete", "my-key").Return(expectedErr)

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

cache := NewLoadable(loadFunc, cache1)

// When
err := cache.Delete("my-key")

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

func TestLoadableGetType(t *testing.T) {
// Given
cache1 := &mocksCache.SetterCacheInterface{}
Expand Down
7 changes: 6 additions & 1 deletion cache/metric.go
Expand Up @@ -32,11 +32,16 @@ func (c *MetricCache) Get(key interface{}) (interface{}, error) {
return result, err
}

// Set sets a value in cache and also records set metric
// Set sets a value from the cache
func (c *MetricCache) Set(key, object interface{}, options *store.Options) error {
return c.cache.Set(key, object, options)
}

// Delete removes a value from the cache
func (c *MetricCache) Delete(key interface{}) error {
return c.cache.Delete(key)
}

// Get obtains a value from cache and also records metrics
func (c *MetricCache) updateMetrics(cache CacheInterface) {
switch current := cache.(type) {
Expand Down
35 changes: 35 additions & 0 deletions cache/metric_test.go
@@ -1,6 +1,7 @@
package cache

import (
"errors"
"testing"

mocksCache "github.com/eko/gocache/test/mocks/cache"
Expand Down Expand Up @@ -84,6 +85,40 @@ func TestMetricGetWhenChainCache(t *testing.T) {
assert.Equal(t, cacheValue, value)
}

func TestMetricDelete(t *testing.T) {
// Given
cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Delete", "my-key").Return(nil)

metrics := &mocksMetrics.MetricsInterface{}

cache := NewMetric(metrics, cache1)

// When
err := cache.Delete("my-key")

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

func TestMetricDeleteWhenError(t *testing.T) {
// Given
expectedErr := errors.New("Unable to delete key")

cache1 := &mocksCache.SetterCacheInterface{}
cache1.On("Delete", "my-key").Return(expectedErr)

metrics := &mocksMetrics.MetricsInterface{}

cache := NewMetric(metrics, cache1)

// When
err := cache.Delete("my-key")

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

func TestMetricGetType(t *testing.T) {
// Given
cache1 := &mocksCache.SetterCacheInterface{}
Expand Down
23 changes: 19 additions & 4 deletions codec/codec.go
Expand Up @@ -6,10 +6,12 @@ import (

// Stats allows to returns some statistics of codec usage
type Stats struct {
Hits int
Miss int
SetSuccess int
SetError int
Hits int
Miss int
SetSuccess int
SetError int
DeleteSuccess int
DeleteError int
}

// Codec represents an instance of a cache store
Expand Down Expand Up @@ -53,6 +55,19 @@ func (c *Codec) Set(key interface{}, value interface{}, options *store.Options)
return err
}

// Delete allows to remove a value for a given key identifier
func (c *Codec) Delete(key interface{}) error {
err := c.store.Delete(key)

if err == nil {
c.stats.DeleteSuccess++
} else {
c.stats.DeleteError++
}

return err
}

// GetStore returns the store associated to this codec
func (c *Codec) GetStore() store.StoreInterface {
return c.store
Expand Down

0 comments on commit 238e4ef

Please sign in to comment.