From 2fd2fba6254cd23fd61670db7859c5c7747a3832 Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Mon, 14 Oct 2019 00:17:12 +0300 Subject: [PATCH 01/11] Add RedisCache Issue #3 --- go.mod | 1 + go.sum | 2 + lru_cache.go | 2 +- options.go | 3 ++ redis_cache.go | 119 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 redis_cache.go diff --git a/go.mod b/go.mod index 21bd98b..4872ee2 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,7 @@ module github.com/go-pkgz/lcw require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-redis/redis v6.15.6+incompatible github.com/hashicorp/golang-lru v0.5.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.8.1 diff --git a/go.sum b/go.sum index 57d795f..40d1d23 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-redis/redis v6.15.6+incompatible h1:H9evprGPLI8+ci7fxQx6WNZHJSb7be8FqJQRhdQZ5Sg= +github.com/go-redis/redis v6.15.6+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= diff --git a/lru_cache.go b/lru_cache.go index 6887550..d5b6b8e 100644 --- a/lru_cache.go +++ b/lru_cache.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" ) -// LruCache wraps lru.LruCache with laoding cache Get and size limits +// LruCache wraps lru.LruCache with loading cache Get and size limits type LruCache struct { options CacheStat diff --git a/options.go b/options.go index 4ee964a..93cb129 100644 --- a/options.go +++ b/options.go @@ -3,6 +3,8 @@ package lcw import ( "errors" "time" + + "github.com/go-redis/redis" ) type options struct { @@ -12,6 +14,7 @@ type options struct { maxCacheSize int64 ttl time.Duration onEvicted func(key string, value Value) + redis *redis.Options } // Option func type diff --git a/redis_cache.go b/redis_cache.go new file mode 100644 index 0000000..063d1dc --- /dev/null +++ b/redis_cache.go @@ -0,0 +1,119 @@ +package lcw + +import ( + "sync/atomic" + "time" + + "github.com/go-redis/redis" + "github.com/pkg/errors" +) + +// RedisCache implements LoadingCache for Redis. +type RedisCache struct { + options + CacheStat + backend *redis.Client + currentSize int64 +} + +// NewRedisCache makes Redis LoadingCache implementation. +func NewRedisCache(opts ...Option) (*RedisCache, error) { + + res := RedisCache{ + options: options{ + ttl: 5 * time.Minute, + }, + } + for _, opt := range opts { + if err := opt(&res.options); err != nil { + return nil, errors.Wrap(err, "failed to set cache option") + } + } + + res.backend = redis.NewClient(res.redis) + + return &res, nil +} + +// Get gets value by key or load with fn if not found in cache +func (c *RedisCache) Get(key string, fn func() (Value, error)) (data Value, err error) { + + v, ok := c.backend.Get(key).Result() + if ok == nil { + atomic.AddInt64(&c.Hits, 1) + return v, nil + } + if ok == redis.Nil { + if data, err = fn(); err != nil { + atomic.AddInt64(&c.Errors, 1) + return data, err + } + } else if ok != nil { + atomic.AddInt64(&c.Errors, 1) + return v, ok + } + atomic.AddInt64(&c.Misses, 1) + + if c.allowed(key, data) { + c.backend.Set(key, data, c.ttl) + } + return data, nil +} + +// Invalidate removes keys with passed predicate fn, i.e. fn(key) should be true to get evicted +func (c *RedisCache) Invalidate(fn func(key string) bool) { + for _, key := range c.backend.Keys("*").Val() { // Keys() returns copy of cache's key, safe to remove directly + if fn(key) { + c.backend.Del(key) + } + } +} + +// Peek returns the key value (or undefined if not found) without updating the "recently used"-ness of the key. +func (c *RedisCache) Peek(key string) (Value, bool) { + ret, err := c.backend.Get(key).Result() + if err != nil { + return nil, false + } + return ret, true +} + +// Purge clears the cache completely. +func (c *RedisCache) Purge() { + c.backend.FlushDB() + +} + +// Delete cache item by key +func (c *RedisCache) Delete(key string) { + c.backend.Del(key) +} + +// Stat returns cache statistics +func (c *RedisCache) Stat() CacheStat { + return CacheStat{ + Hits: c.Hits, + Misses: c.Misses, + Size: c.size(), + Keys: c.keys(), + Errors: c.Errors, + } +} + +func (c *RedisCache) size() int64 { + return 0 +} + +func (c *RedisCache) keys() int { + return int(c.backend.DBSize().Val()) +} + +func (c *RedisCache) allowed(key string, data Value) bool { + if c.backend.DBSize().Val() >= int64(c.maxKeys) { + return false + } + if c.maxKeySize > 0 && len(key) > c.maxKeySize { + return false + } + return true +} From f368c74d0d7bed7c66dbff62c2f3f4a4e067e311 Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Mon, 14 Oct 2019 00:37:15 +0300 Subject: [PATCH 02/11] Fix CI errors --- options.go | 13 ++++++++++++- redis_cache.go | 10 +++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/options.go b/options.go index 93cb129..35c1028 100644 --- a/options.go +++ b/options.go @@ -14,7 +14,7 @@ type options struct { maxCacheSize int64 ttl time.Duration onEvicted func(key string, value Value) - redis *redis.Options + redisOptions *redis.Options } // Option func type @@ -87,3 +87,14 @@ func OnEvicted(fn func(key string, value Value)) Option { return nil } } + +// RedisOptions functional option defines duration. +// Works for RedisCache only +func RedisOptions(Addr string, Password string, DB int) Option { + return func(o *options) error { + o.redisOptions.Addr = Addr + o.redisOptions.Password = Password + o.redisOptions.DB = DB + return nil + } +} diff --git a/redis_cache.go b/redis_cache.go index 063d1dc..bb3cceb 100644 --- a/redis_cache.go +++ b/redis_cache.go @@ -3,6 +3,7 @@ package lcw import ( "sync/atomic" "time" + "unsafe" "github.com/go-redis/redis" "github.com/pkg/errors" @@ -12,8 +13,7 @@ import ( type RedisCache struct { options CacheStat - backend *redis.Client - currentSize int64 + backend *redis.Client } // NewRedisCache makes Redis LoadingCache implementation. @@ -30,7 +30,7 @@ func NewRedisCache(opts ...Option) (*RedisCache, error) { } } - res.backend = redis.NewClient(res.redis) + res.backend = redis.NewClient(res.redisOptions) return &res, nil } @@ -115,5 +115,9 @@ func (c *RedisCache) allowed(key string, data Value) bool { if c.maxKeySize > 0 && len(key) > c.maxKeySize { return false } + if unsafe.Sizeof(data) > (512 * 1024 * 1024) { + return false + } + return true } From fb6f7da6222f366200182f2d65e3a7e17e44423c Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Mon, 14 Oct 2019 00:47:56 +0300 Subject: [PATCH 03/11] Fix CI --- redis_cache.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/redis_cache.go b/redis_cache.go index bb3cceb..8fc6069 100644 --- a/redis_cache.go +++ b/redis_cache.go @@ -3,7 +3,6 @@ package lcw import ( "sync/atomic" "time" - "unsafe" "github.com/go-redis/redis" "github.com/pkg/errors" @@ -115,9 +114,11 @@ func (c *RedisCache) allowed(key string, data Value) bool { if c.maxKeySize > 0 && len(key) > c.maxKeySize { return false } - if unsafe.Sizeof(data) > (512 * 1024 * 1024) { - return false + if s, ok := data.(Sizer); ok { + // Maximum allowed value size in Redis + if s.Size() >= (512 * 1024 * 1024) { + return false + } } - return true } From ddc3df1bfa872b54d964570751c33fa85513c687 Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Tue, 15 Oct 2019 00:53:11 +0300 Subject: [PATCH 04/11] Fix comments --- README.md | 20 ++++++++++---------- go.mod | 6 +++++- go.sum | 30 ++++++++++++++++++++++++++++-- options.go | 14 -------------- redis_cache.go | 27 ++++++++++++++++----------- 5 files changed, 59 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index fa5b26f..5a573e0 100644 --- a/README.md +++ b/README.md @@ -3,26 +3,26 @@ The library adds a thin layer on top of [lru cache](https://github.com/hashicorp/golang-lru) and [patrickmn/go-cache](https://github.com/patrickmn/go-cache). -| Cache name | Constructor | Defaults | Description | -| -------------- | --------------------- | ----------------- | --------------------- | -| LruCache | lcw.NewLruCache | keys=1000 | LRU cache with limits | -| ExpirableCache | lcw.NewExpirableCache | keys=1000, ttl=5m | TTL cache with limits | -| Nop | lcw.NewNopCache | | Do-nothing cache | +| Cache name | Constructor | Defaults | Description | +| -------------- | --------------------- | ----------------- | ----------------------- | +| LruCache | lcw.NewLruCache | keys=1000 | LRU cache with limits | +| ExpirableCache | lcw.NewExpirableCache | keys=1000, ttl=5m | TTL cache with limits | +| RedisCache | lcw.NewRedisCache | ttl=5m | Redis cache with limits | +| Nop | lcw.NewNopCache | | Do-nothing cache | Main features: - - LoadingCache (guava style) - Limit maximum cache size (in bytes) - Limit maximum key size -- Limit maximum size of a value +- Limit maximum size of a value - Limit number of keys -- TTL support (`ExpirableCache` only) -- Callback on eviction event +- TTL support (`ExpirableCache` and `RedisCache`) +- Callback on eviction event (not supported in `RedisCache`) - Functional style invalidation - Functional options - Sane defaults - + ## Install and update `go get -u github.com/go-pkgz/lcw` diff --git a/go.mod b/go.mod index 4872ee2..3f41985 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,16 @@ module github.com/go-pkgz/lcw require ( + github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 // indirect + github.com/alicebob/miniredis v2.5.0+incompatible github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-redis/redis v6.15.6+incompatible + github.com/go-redis/redis/v7 v7.0.0-beta.4 + github.com/gomodule/redigo v2.0.0+incompatible // indirect github.com/hashicorp/golang-lru v0.5.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.8.1 github.com/stretchr/testify v1.3.0 + github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 // indirect ) go 1.13 diff --git a/go.sum b/go.sum index 40d1d23..dbe5a98 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,26 @@ +github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 h1:45bxf7AZMwWcqkLzDAQugVEwedisr5nRJ1r+7LYnv0U= +github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= +github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= +github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-redis/redis v6.15.6+incompatible h1:H9evprGPLI8+ci7fxQx6WNZHJSb7be8FqJQRhdQZ5Sg= -github.com/go-redis/redis v6.15.6+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-redis/redis/v7 v7.0.0-beta.4 h1:p6z7Pde69EGRWvlC++y8aFcaWegyrKHzOBGo0zUACTQ= +github.com/go-redis/redis/v7 v7.0.0-beta.4/go.mod h1:xhhSbUMTsleRPur+Vgx9sUHtyN33bdjxY+9/0n9Ig8s= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -15,3 +30,14 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 h1:1b6PAtenNyhsmo/NKXVe34h7JEZKva1YB/ne7K7mqKM= +github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/options.go b/options.go index 35c1028..4ee964a 100644 --- a/options.go +++ b/options.go @@ -3,8 +3,6 @@ package lcw import ( "errors" "time" - - "github.com/go-redis/redis" ) type options struct { @@ -14,7 +12,6 @@ type options struct { maxCacheSize int64 ttl time.Duration onEvicted func(key string, value Value) - redisOptions *redis.Options } // Option func type @@ -87,14 +84,3 @@ func OnEvicted(fn func(key string, value Value)) Option { return nil } } - -// RedisOptions functional option defines duration. -// Works for RedisCache only -func RedisOptions(Addr string, Password string, DB int) Option { - return func(o *options) error { - o.redisOptions.Addr = Addr - o.redisOptions.Password = Password - o.redisOptions.DB = DB - return nil - } -} diff --git a/redis_cache.go b/redis_cache.go index 8fc6069..fcb3fd0 100644 --- a/redis_cache.go +++ b/redis_cache.go @@ -4,10 +4,13 @@ import ( "sync/atomic" "time" - "github.com/go-redis/redis" + redis "github.com/go-redis/redis/v7" "github.com/pkg/errors" ) +// RedisSizeLimit is maximum allowed value size in Redis +const RedisSizeLimit = 512 * 1024 * 1024 + // RedisCache implements LoadingCache for Redis. type RedisCache struct { options @@ -16,7 +19,7 @@ type RedisCache struct { } // NewRedisCache makes Redis LoadingCache implementation. -func NewRedisCache(opts ...Option) (*RedisCache, error) { +func NewRedisCache(backend *redis.Client, opts ...Option) (*RedisCache, error) { res := RedisCache{ options: options{ @@ -29,7 +32,7 @@ func NewRedisCache(opts ...Option) (*RedisCache, error) { } } - res.backend = redis.NewClient(res.redisOptions) + res.backend = backend return &res, nil } @@ -37,19 +40,19 @@ func NewRedisCache(opts ...Option) (*RedisCache, error) { // Get gets value by key or load with fn if not found in cache func (c *RedisCache) Get(key string, fn func() (Value, error)) (data Value, err error) { - v, ok := c.backend.Get(key).Result() - if ok == nil { + v, getErr := c.backend.Get(key).Result() + switch getErr { + case nil: atomic.AddInt64(&c.Hits, 1) return v, nil - } - if ok == redis.Nil { + case redis.Nil: if data, err = fn(); err != nil { atomic.AddInt64(&c.Errors, 1) return data, err } - } else if ok != nil { + default: atomic.AddInt64(&c.Errors, 1) - return v, ok + return v, getErr } atomic.AddInt64(&c.Misses, 1) @@ -115,8 +118,10 @@ func (c *RedisCache) allowed(key string, data Value) bool { return false } if s, ok := data.(Sizer); ok { - // Maximum allowed value size in Redis - if s.Size() >= (512 * 1024 * 1024) { + if c.maxValueSize > 0 && (s.Size() >= c.maxValueSize || s.Size() >= RedisSizeLimit) { + return false + } + if c.maxValueSize <= 0 && s.Size() >= RedisSizeLimit { return false } } From 2a071228a8a7afdd9515f9156a8557b6b8dc091f Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Tue, 15 Oct 2019 01:02:22 +0300 Subject: [PATCH 05/11] clean a bit go.sum and go.mod --- go.mod | 3 --- go.sum | 24 ------------------------ 2 files changed, 27 deletions(-) diff --git a/go.mod b/go.mod index 3f41985..2035511 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,13 @@ module github.com/go-pkgz/lcw require ( - github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 // indirect github.com/alicebob/miniredis v2.5.0+incompatible github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-redis/redis/v7 v7.0.0-beta.4 - github.com/gomodule/redigo v2.0.0+incompatible // indirect github.com/hashicorp/golang-lru v0.5.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.8.1 github.com/stretchr/testify v1.3.0 - github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 // indirect ) go 1.13 diff --git a/go.sum b/go.sum index dbe5a98..a5a0b78 100644 --- a/go.sum +++ b/go.sum @@ -1,26 +1,13 @@ -github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 h1:45bxf7AZMwWcqkLzDAQugVEwedisr5nRJ1r+7LYnv0U= -github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-redis/redis/v7 v7.0.0-beta.4 h1:p6z7Pde69EGRWvlC++y8aFcaWegyrKHzOBGo0zUACTQ= github.com/go-redis/redis/v7 v7.0.0-beta.4/go.mod h1:xhhSbUMTsleRPur+Vgx9sUHtyN33bdjxY+9/0n9Ig8s= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= -github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -30,14 +17,3 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 h1:1b6PAtenNyhsmo/NKXVe34h7JEZKva1YB/ne7K7mqKM= -github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From db684dcf90923e9deca4c90c410a69678a25388b Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Tue, 15 Oct 2019 01:06:41 +0300 Subject: [PATCH 06/11] Add redis_cache_test.go --- redis_cache_test.go | 132 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 redis_cache_test.go diff --git a/redis_cache_test.go b/redis_cache_test.go new file mode 100644 index 0000000..85fd146 --- /dev/null +++ b/redis_cache_test.go @@ -0,0 +1,132 @@ +package lcw + +import ( + "fmt" + "log" + "sync/atomic" + "testing" + "time" + + "github.com/alicebob/miniredis" + redis "github.com/go-redis/redis/v7" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// newTestRedis returns a redis.Cmdable. +func newTestRedisServer() *miniredis.Miniredis { + mr, err := miniredis.Run() + if err != nil { + panic(err) + } + + return mr +} + +func TestExpirableRedisCache(t *testing.T) { + server := newTestRedisServer() + client := redis.NewClient(&redis.Options{ + Addr: server.Addr()}) + lc, err := NewRedisCache(client, MaxKeys(5), TTL(time.Second*6)) + if err != nil { + log.Fatalf("can't make redis cache, %v", err) + } + log.Printf("TTL: %s", lc.ttl) + require.NoError(t, err) + for i := 0; i < 5; i++ { + _, e := lc.Get(fmt.Sprintf("key-%d", i), func() (Value, error) { + return fmt.Sprintf("result-%d", i), nil + }) + assert.NoError(t, e) + server.FastForward(1000 * time.Millisecond) + } + + assert.Equal(t, 5, lc.Stat().Keys) + assert.Equal(t, int64(5), lc.Stat().Misses) + + _, e := lc.Get("key-xx", func() (Value, error) { + return "result-xx", nil + }) + assert.NoError(t, e) + assert.Equal(t, 5, lc.Stat().Keys) + assert.Equal(t, int64(6), lc.Stat().Misses) + + server.FastForward(1000 * time.Millisecond) + assert.Equal(t, 4, lc.Stat().Keys) + + server.FastForward(4000 * time.Millisecond) + assert.Equal(t, 0, lc.keys()) + +} + +func TestRedisCache(t *testing.T) { + var coldCalls int32 + + server := newTestRedisServer() + client := redis.NewClient(&redis.Options{ + Addr: server.Addr()}) + lc, err := NewRedisCache(client, MaxKeys(5), MaxValSize(10)) + if err != nil { + log.Fatalf("can't make redis cache, %v", err) + } + // put 5 keys to cache + for i := 0; i < 5; i++ { + res, e := lc.Get(fmt.Sprintf("key-%d", i), func() (Value, error) { + atomic.AddInt32(&coldCalls, 1) + return fmt.Sprintf("result-%d", i), nil + }) + assert.Nil(t, e) + assert.Equal(t, fmt.Sprintf("result-%d", i), res.(string)) + assert.Equal(t, int32(i+1), atomic.LoadInt32(&coldCalls)) + } + + // check if really cached + res, err := lc.Get("key-3", func() (Value, error) { + return "result-blah", nil + }) + assert.Nil(t, err) + assert.Equal(t, "result-3", res.(string), "should be cached") + + // try to cache after maxKeys reached + res, err = lc.Get("key-X", func() (Value, error) { + return "result-X", nil + }) + assert.Nil(t, err) + assert.Equal(t, "result-X", res.(string)) + assert.Equal(t, int64(5), lc.backend.DBSize().Val()) + + // put to cache and make sure it cached + res, err = lc.Get("key-Z", func() (Value, error) { + return "result-Z", nil + }) + assert.Nil(t, err) + assert.Equal(t, "result-Z", res.(string)) + + res, err = lc.Get("key-Z", func() (Value, error) { + return "result-Zzzz", nil + }) + assert.Nil(t, err) + assert.Equal(t, "result-Zzzz", res.(string), "got non-cached value") + assert.Equal(t, 5, lc.keys()) +} + +func TestRedisCache_BadOptions(t *testing.T) { + server := newTestRedisServer() + client := redis.NewClient(&redis.Options{ + Addr: server.Addr()}) + + _, err := NewRedisCache(client, MaxCacheSize(-1)) + assert.EqualError(t, err, "failed to set cache option: negative max cache size") + + _, err = NewRedisCache(client, MaxCacheSize(-1)) + assert.EqualError(t, err, "failed to set cache option: negative max cache size") + + _, err = NewRedisCache(client, MaxKeys(-1)) + assert.EqualError(t, err, "failed to set cache option: negative max keys") + + _, err = NewRedisCache(client, MaxValSize(-1)) + assert.EqualError(t, err, "failed to set cache option: negative max value size") + + _, err = NewRedisCache(client, TTL(-1)) + assert.EqualError(t, err, "failed to set cache option: negative ttl") +} From 18c8b03388b31dbf0f0d18216be97dec688fa4c1 Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Tue, 15 Oct 2019 01:10:12 +0300 Subject: [PATCH 07/11] remove debug string from redis_cache_test.go --- redis_cache_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/redis_cache_test.go b/redis_cache_test.go index 85fd146..d89fe3e 100644 --- a/redis_cache_test.go +++ b/redis_cache_test.go @@ -31,7 +31,6 @@ func TestExpirableRedisCache(t *testing.T) { if err != nil { log.Fatalf("can't make redis cache, %v", err) } - log.Printf("TTL: %s", lc.ttl) require.NoError(t, err) for i := 0; i < 5; i++ { _, e := lc.Get(fmt.Sprintf("key-%d", i), func() (Value, error) { From 97af5f555310332ecdc5818b5fff3ea8b453a947 Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Tue, 15 Oct 2019 01:35:51 +0300 Subject: [PATCH 08/11] Increase test coverage --- redis_cache_test.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/redis_cache_test.go b/redis_cache_test.go index d89fe3e..3fb3cb9 100644 --- a/redis_cache_test.go +++ b/redis_cache_test.go @@ -64,7 +64,7 @@ func TestRedisCache(t *testing.T) { server := newTestRedisServer() client := redis.NewClient(&redis.Options{ Addr: server.Addr()}) - lc, err := NewRedisCache(client, MaxKeys(5), MaxValSize(10)) + lc, err := NewRedisCache(client, MaxKeys(5), MaxValSize(10), MaxKeySize(10)) if err != nil { log.Fatalf("can't make redis cache, %v", err) } @@ -107,6 +107,29 @@ func TestRedisCache(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "result-Zzzz", res.(string), "got non-cached value") assert.Equal(t, 5, lc.keys()) + + res, err = lc.Get("key-Zzzzzzz", func() (Value, error) { + return "result-Zzzz", nil + }) + assert.Nil(t, err) + assert.Equal(t, "result-Zzzz", res.(string), "got non-cached value") + assert.Equal(t, 5, lc.keys()) + + val, ok := lc.Peek("key-3") + assert.True(t, ok) + assert.Equal(t, "result-3", val) + + val, ok = lc.Peek("key-99") + assert.False(t, ok) + assert.Equal(t, nil, val) + + lc.Delete("key-0") + assert.Equal(t, 4, lc.Stat().Keys) + + val, ok = lc.Peek("key-0") + assert.False(t, ok) + assert.Equal(t, nil, val) + } func TestRedisCache_BadOptions(t *testing.T) { From 79560e5c3f36d41d7ecf5ecfb9ca96a274114b6b Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Tue, 15 Oct 2019 01:51:11 +0300 Subject: [PATCH 09/11] Add RedisCache to cache_test.go --- cache_test.go | 9 +++++++++ redis_cache_test.go | 15 --------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/cache_test.go b/cache_test.go index 6fb2695..35fc8fa 100644 --- a/cache_test.go +++ b/cache_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + redis "github.com/go-redis/redis/v7" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -515,6 +516,14 @@ func cachesTestList(t *testing.T, opts ...Option) []countedCache { lc, err := NewLruCache(opts...) require.NoError(t, err, "can't make lru cache") caches = append(caches, lc) + + server := newTestRedisServer() + client := redis.NewClient(&redis.Options{ + Addr: server.Addr()}) + rc, err := NewRedisCache(client, opts...) + require.NoError(t, err, "can't make redis cache") + caches = append(caches, rc) + return caches } diff --git a/redis_cache_test.go b/redis_cache_test.go index 3fb3cb9..94d75d7 100644 --- a/redis_cache_test.go +++ b/redis_cache_test.go @@ -115,21 +115,6 @@ func TestRedisCache(t *testing.T) { assert.Equal(t, "result-Zzzz", res.(string), "got non-cached value") assert.Equal(t, 5, lc.keys()) - val, ok := lc.Peek("key-3") - assert.True(t, ok) - assert.Equal(t, "result-3", val) - - val, ok = lc.Peek("key-99") - assert.False(t, ok) - assert.Equal(t, nil, val) - - lc.Delete("key-0") - assert.Equal(t, 4, lc.Stat().Keys) - - val, ok = lc.Peek("key-0") - assert.False(t, ok) - assert.Equal(t, nil, val) - } func TestRedisCache_BadOptions(t *testing.T) { From 8293bbbfc79e67b8189f51bacb56346218f4fcc8 Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Tue, 15 Oct 2019 23:12:53 +0300 Subject: [PATCH 10/11] fix tests --- cache_test.go | 82 ++++++++++++++++++++++++++++++++++++++------- redis_cache.go | 9 +++-- redis_cache_test.go | 11 ++++++ 3 files changed, 87 insertions(+), 15 deletions(-) diff --git a/cache_test.go b/cache_test.go index 35fc8fa..9080b95 100644 --- a/cache_test.go +++ b/cache_test.go @@ -113,6 +113,9 @@ func TestCache_MaxValueSize(t *testing.T) { res, err = c.Get("key-Z", func() (Value, error) { return sizedString("result-Zzzz"), nil }) + if s, ok := res.(string); ok { + res = sizedString(s) + } assert.NoError(t, err) assert.Equal(t, sizedString("result-Z"), res.(sizedString), "got cached value") @@ -120,12 +123,18 @@ func TestCache_MaxValueSize(t *testing.T) { res, err = c.Get("key-Big", func() (Value, error) { return sizedString("1234567890"), nil }) + if s, ok := res.(string); ok { + res = sizedString(s) + } assert.NoError(t, err) assert.Equal(t, sizedString("1234567890"), res.(sizedString)) res, err = c.Get("key-Big", func() (Value, error) { return sizedString("result-big"), nil }) + if s, ok := res.(string); ok { + res = sizedString(s) + } assert.NoError(t, err) assert.Equal(t, sizedString("result-big"), res.(sizedString), "got not cached value") @@ -155,28 +164,39 @@ func TestCache_MaxCacheSize(t *testing.T) { return sizedString("result-Z"), nil }) assert.NoError(t, err) + if s, ok := res.(string); ok { + res = sizedString(s) + } assert.Equal(t, sizedString("result-Z"), res.(sizedString)) - res, err = c.Get("key-Z", func() (Value, error) { return sizedString("result-Zzzz"), nil }) + if s, ok := res.(string); ok { + res = sizedString(s) + } assert.NoError(t, err) assert.Equal(t, sizedString("result-Z"), res.(sizedString), "got cached value") - assert.Equal(t, int64(8), c.size()) - + if _, ok := c.(*RedisCache); !ok { + assert.Equal(t, int64(8), c.size()) + } _, err = c.Get("key-Z2", func() (Value, error) { return sizedString("result-Y"), nil }) assert.Nil(t, err) - assert.Equal(t, int64(16), c.size()) + if _, ok := c.(*RedisCache); !ok { + assert.Equal(t, int64(16), c.size()) + } // this will cause removal _, err = c.Get("key-Z3", func() (Value, error) { return sizedString("result-Z"), nil }) assert.Nil(t, err) - assert.Equal(t, int64(16), c.size()) - assert.Equal(t, 2, c.keys()) + if _, ok := c.(*RedisCache); !ok { + assert.Equal(t, int64(16), c.size()) + // Due RedisCache does not support MaxCacheSize this assert should be skipped + assert.Equal(t, 2, c.keys()) + } }) } } @@ -372,11 +392,14 @@ func TestCache_Delete(t *testing.T) { require.Nil(t, err) } assert.Equal(t, 1000, c.Stat().Keys) - assert.Equal(t, int64(9890), c.Stat().Size) - + if _, ok := c.(*RedisCache); !ok { + assert.Equal(t, int64(9890), c.Stat().Size) + } c.Delete("key-2") assert.Equal(t, 999, c.Stat().Keys) - assert.Equal(t, int64(9890-8), c.Stat().Size) + if _, ok := c.(*RedisCache); !ok { + assert.Equal(t, int64(9890-8), c.Stat().Size) + } }) } } @@ -393,8 +416,12 @@ func TestCache_DeleteWithEvent(t *testing.T) { caches := cachesTestList(t, OnEvicted(onEvict)) for _, c := range caches { + evKey, evVal, evCount = "", "", 0 t.Run(strings.Replace(fmt.Sprintf("%T", c), "*lcw.", "", 1), func(t *testing.T) { + if _, ok := c.(*RedisCache); ok { + t.Skip("RedisCache doesn't support delete events") + } // fill cache for i := 0; i < 1000; i++ { _, err := c.Get(fmt.Sprintf("key-%d", i), func() (Value, error) { @@ -426,25 +453,45 @@ func TestCache_Stats(t *testing.T) { require.Nil(t, err) } stats := c.Stat() - assert.Equal(t, CacheStat{Hits: 0, Misses: 100, Keys: 100, Size: 890}, stats) + switch c.(type) { + case *RedisCache: + assert.Equal(t, CacheStat{Hits: 0, Misses: 100, Keys: 100, Size: 0}, stats) + default: + assert.Equal(t, CacheStat{Hits: 0, Misses: 100, Keys: 100, Size: 890}, stats) + } _, err := c.Get("key-1", func() (Value, error) { return "xyz", nil }) require.NoError(t, err) - assert.Equal(t, CacheStat{Hits: 1, Misses: 100, Keys: 100, Size: 890}, c.Stat()) + switch c.(type) { + case *RedisCache: + assert.Equal(t, CacheStat{Hits: 1, Misses: 100, Keys: 100, Size: 0}, c.Stat()) + default: + assert.Equal(t, CacheStat{Hits: 1, Misses: 100, Keys: 100, Size: 890}, c.Stat()) + } _, err = c.Get("key-1123", func() (Value, error) { return sizedString("xyz"), nil }) require.NoError(t, err) - assert.Equal(t, CacheStat{Hits: 1, Misses: 101, Keys: 101, Size: 893}, c.Stat()) + switch c.(type) { + case *RedisCache: + assert.Equal(t, CacheStat{Hits: 1, Misses: 101, Keys: 101, Size: 0}, c.Stat()) + default: + assert.Equal(t, CacheStat{Hits: 1, Misses: 101, Keys: 101, Size: 893}, c.Stat()) + } _, err = c.Get("key-9999", func() (Value, error) { return nil, errors.New("err") }) require.NotNil(t, err) - assert.Equal(t, CacheStat{Hits: 1, Misses: 101, Keys: 101, Size: 893, Errors: 1}, c.Stat()) + switch c.(type) { + case *RedisCache: + assert.Equal(t, CacheStat{Hits: 1, Misses: 101, Keys: 101, Size: 0, Errors: 1}, c.Stat()) + default: + assert.Equal(t, CacheStat{Hits: 1, Misses: 101, Keys: 101, Size: 893, Errors: 1}, c.Stat()) + } }) } @@ -530,3 +577,12 @@ func cachesTestList(t *testing.T, opts ...Option) []countedCache { type sizedString string func (s sizedString) Size() int { return len(s) } + +func (s sizedString) UnmarshalBinary(data []byte) error { + s = sizedString(data) + return nil +} + +func (s sizedString) MarshalBinary() (data []byte, err error) { + return []byte(s), nil +} diff --git a/redis_cache.go b/redis_cache.go index fcb3fd0..393c1db 100644 --- a/redis_cache.go +++ b/redis_cache.go @@ -57,7 +57,12 @@ func (c *RedisCache) Get(key string, fn func() (Value, error)) (data Value, err atomic.AddInt64(&c.Misses, 1) if c.allowed(key, data) { - c.backend.Set(key, data, c.ttl) + _, setErr := c.backend.Set(key, data, c.ttl).Result() + if setErr != nil { + atomic.AddInt64(&c.Errors, 1) + return data, setErr + } + } return data, nil } @@ -111,7 +116,7 @@ func (c *RedisCache) keys() int { } func (c *RedisCache) allowed(key string, data Value) bool { - if c.backend.DBSize().Val() >= int64(c.maxKeys) { + if c.maxKeys > 0 && c.backend.DBSize().Val() >= int64(c.maxKeys) { return false } if c.maxKeySize > 0 && len(key) > c.maxKeySize { diff --git a/redis_cache_test.go b/redis_cache_test.go index 94d75d7..0da8fd4 100644 --- a/redis_cache_test.go +++ b/redis_cache_test.go @@ -58,6 +58,17 @@ func TestExpirableRedisCache(t *testing.T) { } +// func Test1(t *testing.T) { +// server := newTestRedisServer() +// client := redis.NewClient(&redis.Options{ +// Addr: server.Addr()}) +// lc, err := NewRedisCache(client, MaxKeys(5), MaxValSize(10), MaxKeySize(10)) +// if err != nil { +// log.Fatalf("can't make redis cache, %v", err) +// } + +// } + func TestRedisCache(t *testing.T) { var coldCalls int32 From 89803eb4d1f4f676157326c550cd379be84cf635 Mon Sep 17 00:00:00 2001 From: Dmitry Tyzhnenko Date: Tue, 15 Oct 2019 23:18:18 +0300 Subject: [PATCH 11/11] fix tests --- cache_test.go | 5 ----- go.mod | 3 +++ go.sum | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/cache_test.go b/cache_test.go index 9080b95..e7636f8 100644 --- a/cache_test.go +++ b/cache_test.go @@ -578,11 +578,6 @@ type sizedString string func (s sizedString) Size() int { return len(s) } -func (s sizedString) UnmarshalBinary(data []byte) error { - s = sizedString(data) - return nil -} - func (s sizedString) MarshalBinary() (data []byte, err error) { return []byte(s), nil } diff --git a/go.mod b/go.mod index 2035511..3f41985 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,16 @@ module github.com/go-pkgz/lcw require ( + github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 // indirect github.com/alicebob/miniredis v2.5.0+incompatible github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-redis/redis/v7 v7.0.0-beta.4 + github.com/gomodule/redigo v2.0.0+incompatible // indirect github.com/hashicorp/golang-lru v0.5.0 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.8.1 github.com/stretchr/testify v1.3.0 + github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 // indirect ) go 1.13 diff --git a/go.sum b/go.sum index a5a0b78..dbe5a98 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,26 @@ +github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 h1:45bxf7AZMwWcqkLzDAQugVEwedisr5nRJ1r+7LYnv0U= +github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI= github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-redis/redis/v7 v7.0.0-beta.4 h1:p6z7Pde69EGRWvlC++y8aFcaWegyrKHzOBGo0zUACTQ= github.com/go-redis/redis/v7 v7.0.0-beta.4/go.mod h1:xhhSbUMTsleRPur+Vgx9sUHtyN33bdjxY+9/0n9Ig8s= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -17,3 +30,14 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036 h1:1b6PAtenNyhsmo/NKXVe34h7JEZKva1YB/ne7K7mqKM= +github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=