diff --git a/.travis.yml b/.travis.yml index 3c6ef3e..0e3d250 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ go: install: true +go_import_path: github.com/go-pkgz/lcw + before_install: - export TZ=America/Chicago - curl -L https://git.io/vp6lP | sh diff --git a/README.md b/README.md index e0c52d1..3af0bf0 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,13 @@ 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). -It exposes 3 caches, implementing `LoadingCache` interface: +| 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 | + -1. `LruCache` - LRU cache with limits, created with `lcw.NewLruCache` -1. `ExpirableCache` - TTL cache with limits, created with `lcw.NewExpirableCache` -1. `Nop` - do-nothing cache - Main features: - LoadingCache (guava style) @@ -44,7 +45,7 @@ s := val.(string) // cached value ## Details -- All byte-size limits work for values implementing `lcw.Sizer` interface +- All byte-size limits (MaxCacheSize and MaxValSize) only work for values implementing `lcw.Sizer` interface. - Negative limits (max options) rejected - `lgr.Value` wraps `interface{}` and should be converted back to the concrete type. - The implementation started as a part of [remark42](https://github.com/umputun/remark) and later on moved to [go-pkgz/rest](https://github.com/go-pkgz/rest/tree/master/cache) library and finaly generalized to become `lcw`. diff --git a/cache_test.go b/cache_test.go index 037fb27..35f3f26 100644 --- a/cache_test.go +++ b/cache_test.go @@ -314,11 +314,20 @@ func TestCache_Invalidate(t *testing.T) { assert.Equal(t, "result-xxx", res.(string), "not from the cache") }) } +} + +type counts interface { + size() int64 // cache size in bytes + keys() int // number of keys in cache +} +type countedCache interface { + LoadingCache + counts } -func cachesTestList(t *testing.T, opts ...Option) []LoadingCache { - var caches []LoadingCache +func cachesTestList(t *testing.T, opts ...Option) []countedCache { + var caches []countedCache ec, err := NewExpirableCache(opts...) require.NoError(t, err, "can't make exp cache") caches = append(caches, ec) diff --git a/expirable_cache.go b/expirable_cache.go index 47faf41..a146d1c 100644 --- a/expirable_cache.go +++ b/expirable_cache.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" ) +// ExpirableCache implements LoadingCache with TTL. type ExpirableCache struct { options currentSize int64 @@ -15,7 +16,7 @@ type ExpirableCache struct { backend *cache.Cache } -// NewLruCache makes LoadingCache (lru) implementation, 1000 max keys by default +// NewExpirableCache makes expirable LoadingCache implementation, 1000 max keys by default and 5s TTL func NewExpirableCache(opts ...Option) (*ExpirableCache, error) { res := ExpirableCache{ diff --git a/go.mod b/go.mod index 2a7a7c2..42c8a66 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,9 @@ module github.com/go-pkgz/lcw require ( + github.com/davecgh/go-spew v1.1.1 // 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 ) diff --git a/go.sum b/go.sum index 65caab4..57d795f 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,11 @@ 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/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= +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= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/interface.go b/interface.go index 9076c1c..b9c6af2 100644 --- a/interface.go +++ b/interface.go @@ -15,9 +15,6 @@ type LoadingCache interface { Peek(key string) (Value, bool) Invalidate(fn func(key string) bool) Purge() - - size() int64 // cache size in bytes - keys() int // number of keys in cache } // Nop is do-nothing implementation of LoadingCache @@ -39,9 +36,3 @@ func (n *Nop) Invalidate(fn func(key string) bool) {} // Purge does nothing for nop cache func (n *Nop) Purge() {} - -// Size is always 0 for nop cache -func (n *Nop) size() int64 { return 0 } - -// Keys is always 0 for nop cache -func (n *Nop) keys() int { return 0 } diff --git a/interface_test.go b/interface_test.go index 56453d1..533814e 100644 --- a/interface_test.go +++ b/interface_test.go @@ -40,7 +40,4 @@ func TestNop_Peek(t *testing.T) { _, ok := c.Peek("key1") assert.False(t, ok) - - assert.Equal(t, 0, c.keys()) - assert.Equal(t, int64(0), c.size()) } diff --git a/lru_cache.go b/lru_cache.go index e41b2da..ed25be6 100644 --- a/lru_cache.go +++ b/lru_cache.go @@ -14,7 +14,7 @@ type LruCache struct { currentSize int64 } -// NewLruCache makes LoadingCache (lru) implementation, 1000 max keys by default +// NewLruCache makes LRU LoadingCache implementation, 1000 max keys by default func NewLruCache(opts ...Option) (*LruCache, error) { res := LruCache{ diff --git a/options.go b/options.go index 8fecff2..83835c2 100644 --- a/options.go +++ b/options.go @@ -64,8 +64,8 @@ func MaxCacheSize(max int64) Option { } } -// MaxCacheSize functional option defines the total size of cached data. -// By default it is 0, which means unlimited. +// TTL functional option defines duration. +// Works for ExpirableCache only func TTL(ttl time.Duration) Option { return func(o *options) error { if ttl < 0 {