Documentation
¶
Overview ¶
Package lcw adds a thin layer on top of lru and expirable cache providing more limits and common interface. The primary method to get (and set) data to/from the cache is LoadingCache.Get returning stored data for a given key or call provided func to retrieve and store, similar to Guava loading cache. Limits allow max values for key size, number of keys, value size and total size of values in the cache. CacheStat gives general stats on cache performance. 3 flavors of cache provided - NoP (do-nothing cache), ExpirableCache (TTL based), and LruCache
Example (LoadingCacheMutability) ¶
nolint:govet //false positive due to example name ExampleLoadingCacheMutability illustrates changing mutable stored item outside of cache, works only for non-Redis cache.
c, err := NewExpirableCache(MaxKeys(10), TTL(time.Minute*30)) // make expirable cache (30m TTL) with up to 10 keys if err != nil { panic("can' make cache") } defer c.Close() mutableSlice := []string{"key1", "key2"} // put mutableSlice in "mutableSlice" cache key _, _ = c.Get("mutableSlice", func() (interface{}, error) { return mutableSlice, nil }) // get from cache, func won't run because mutableSlice is cached // value is original now v, _ := c.Get("mutableSlice", func() (interface{}, error) { return nil, nil }) fmt.Printf("got %v slice from cache\n", v) mutableSlice[0] = "another_key_1" mutableSlice[1] = "another_key_2" // get from cache, func won't run because mutableSlice is cached // value is changed inside the cache now because mutableSlice stored as-is, in mutable state v, _ = c.Get("mutableSlice", func() (interface{}, error) { return nil, nil }) fmt.Printf("got %v slice from cache after it's change outside of cache\n", v)
Output: got [key1 key2] slice from cache got [another_key_1 another_key_2] slice from cache after it's change outside of cache
Index ¶
- Constants
- type CacheStat
- type ExpirableCache
- func (c *ExpirableCache) Close() error
- func (c *ExpirableCache) Delete(key string)
- func (c *ExpirableCache) Get(key string, fn func() (interface{}, error)) (data interface{}, err error)
- func (c *ExpirableCache) Invalidate(fn func(key string) bool)
- func (c *ExpirableCache) Keys() (res []string)
- func (c *ExpirableCache) Peek(key string) (interface{}, bool)
- func (c *ExpirableCache) Purge()
- func (c *ExpirableCache) Stat() CacheStat
- type FlusherRequest
- type Key
- type LoadingCache
- type LruCache
- func (c *LruCache) Close() error
- func (c *LruCache) Delete(key string)
- func (c *LruCache) Get(key string, fn func() (interface{}, error)) (data interface{}, err error)
- func (c *LruCache) Invalidate(fn func(key string) bool)
- func (c *LruCache) Keys() (res []string)
- func (c *LruCache) Peek(key string) (interface{}, bool)
- func (c *LruCache) Purge()
- func (c *LruCache) Stat() CacheStat
- type Nop
- func (n *Nop) Close() error
- func (n *Nop) Delete(string)
- func (n *Nop) Get(_ string, fn func() (interface{}, error)) (interface{}, error)
- func (n *Nop) Invalidate(func(key string) bool)
- func (n *Nop) Keys() []string
- func (n *Nop) Peek(string) (interface{}, bool)
- func (n *Nop) Purge()
- func (n *Nop) Stat() CacheStat
- type Option
- type RedisCache
- func (c *RedisCache) Close() error
- func (c *RedisCache) Delete(key string)
- func (c *RedisCache) Get(key string, fn func() (interface{}, error)) (data interface{}, err error)
- func (c *RedisCache) Invalidate(fn func(key string) bool)
- func (c *RedisCache) Keys() (res []string)
- func (c *RedisCache) Peek(key string) (interface{}, bool)
- func (c *RedisCache) Purge()
- func (c *RedisCache) Stat() CacheStat
- type Scache
- type Sizer
Examples ¶
Constants ¶
const RedisValueSizeLimit = 512 * 1024 * 1024
RedisValueSizeLimit is maximum allowed value size in Redis
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ExpirableCache ¶ added in v0.2.0
type ExpirableCache struct { CacheStat // contains filtered or unexported fields }
ExpirableCache implements LoadingCache with TTL.
func NewExpirableCache ¶ added in v0.2.0
func NewExpirableCache(opts ...Option) (*ExpirableCache, error)
NewExpirableCache makes expirable LoadingCache implementation, 1000 max keys by default and 5m TTL
func (*ExpirableCache) Close ¶ added in v0.6.0
func (c *ExpirableCache) Close() error
Close kills cleanup goroutine
func (*ExpirableCache) Delete ¶ added in v0.3.0
func (c *ExpirableCache) Delete(key string)
Delete cache item by key
func (*ExpirableCache) Get ¶ added in v0.2.0
func (c *ExpirableCache) Get(key string, fn func() (interface{}, error)) (data interface{}, err error)
Get gets value by key or load with fn if not found in cache
func (*ExpirableCache) Invalidate ¶ added in v0.2.0
func (c *ExpirableCache) Invalidate(fn func(key string) bool)
Invalidate removes keys with passed predicate fn, i.e. fn(key) should be true to get evicted
func (*ExpirableCache) Keys ¶ added in v0.5.0
func (c *ExpirableCache) Keys() (res []string)
Keys returns cache keys
func (*ExpirableCache) Peek ¶ added in v0.2.0
func (c *ExpirableCache) Peek(key string) (interface{}, bool)
Peek returns the key value (or undefined if not found) without updating the "recently used"-ness of the key.
func (*ExpirableCache) Purge ¶ added in v0.2.0
func (c *ExpirableCache) Purge()
Purge clears the cache completely.
func (*ExpirableCache) Stat ¶ added in v0.2.0
func (c *ExpirableCache) Stat() CacheStat
Stat returns cache statistics
type FlusherRequest ¶ added in v0.5.0
type FlusherRequest struct {
// contains filtered or unexported fields
}
FlusherRequest used as input for cache.Flush
func Flusher ¶ added in v0.5.0
func Flusher(partition string) FlusherRequest
Flusher makes new FlusherRequest with empty scopes
func (FlusherRequest) Scopes ¶ added in v0.5.0
func (f FlusherRequest) Scopes(scopes ...string) FlusherRequest
Scopes adds scopes to FlusherRequest
type Key ¶ added in v0.5.0
type Key struct {
// contains filtered or unexported fields
}
Key for scoped cache. Created foe given partition (can be empty) and set with ID and Scopes. example: k := NewKey("sys1").ID(postID).Scopes("last_posts", customer_id)
type LoadingCache ¶
type LoadingCache interface { Get(key string, fn func() (interface{}, error)) (val interface{}, err error) // load or get from cache Peek(key string) (interface{}, bool) // get from cache by key Invalidate(fn func(key string) bool) // invalidate items for func(key) == true Delete(key string) // delete by key Purge() // clear cache Stat() CacheStat // cache stats Keys() []string // list of all keys Close() error // close open connections }
LoadingCache defines guava-like cache with Get method returning cached value ao retrieving it if not in cache
func New ¶ added in v0.4.0
func New(uri string) (LoadingCache, error)
New parses uri and makes any of supported caches supported URIs:
- redis://<ip>:<port>?db=123&max_keys=10
- mem://lru?max_keys=10&max_cache_size=1024
- mem://expirable?ttl=30s&max_val_size=100
- nop://
type LruCache ¶ added in v0.2.0
type LruCache struct { CacheStat // contains filtered or unexported fields }
LruCache wraps lru.LruCache with loading cache Get and size limits
Example ¶
LruCache illustrates the use of LRU loading cache
// set up test server for single response var hitCount int ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.String() == "/post/42" && hitCount == 0 { _, _ = w.Write([]byte("<html><body>test response</body></html>")) return } w.WriteHeader(404) })) // load page function loadURL := func(url string) (string, error) { resp, err := http.Get(url) // nolint if err != nil { return "", err } b, err := io.ReadAll(resp.Body) _ = resp.Body.Close() if err != nil { return "", err } return string(b), nil } // fixed size LRU cache, 100 items, up to 10k in total size cache, err := NewLruCache(MaxKeys(100), MaxCacheSize(10*1024)) if err != nil { log.Printf("can't make lru cache, %v", err) } // url not in cache, load data url := ts.URL + "/post/42" val, err := cache.Get(url, func() (val interface{}, err error) { return loadURL(url) }) if err != nil { log.Fatalf("can't load url %s, %v", url, err) } fmt.Println(val.(string)) // url not in cache, load data val, err = cache.Get(url, func() (val interface{}, err error) { return loadURL(url) }) if err != nil { log.Fatalf("can't load url %s, %v", url, err) } fmt.Println(val.(string)) // url cached, skip load and get from the cache val, err = cache.Get(url, func() (val interface{}, err error) { return loadURL(url) }) if err != nil { log.Fatalf("can't load url %s, %v", url, err) } fmt.Println(val.(string)) // get cache stats stats := cache.Stat() fmt.Printf("%+v\n", stats) // close test HTTP server after all log.Fatalf are passed ts.Close()
Output: <html><body>test response</body></html> <html><body>test response</body></html> <html><body>test response</body></html> {hits:2, misses:1, ratio:0.67, keys:1, size:0, errors:0}
func NewLruCache ¶ added in v0.2.0
NewLruCache makes LRU LoadingCache implementation, 1000 max keys by default
func (*LruCache) Invalidate ¶ added in v0.2.0
Invalidate removes keys with passed predicate fn, i.e. fn(key) should be true to get evicted
func (*LruCache) Peek ¶ added in v0.2.0
Peek returns the key value (or undefined if not found) without updating the "recently used"-ness of the key.
type Nop ¶
type Nop struct{}
Nop is do-nothing implementation of LoadingCache
func (*Nop) Invalidate ¶
Invalidate does nothing for nop cache
type Option ¶
type Option func(o *options) error
Option func type
func MaxCacheSize ¶
MaxCacheSize functional option defines the total size of cached data. By default it is 0, which means unlimited.
func MaxKeySize ¶
MaxKeySize functional option defines the largest key's size allowed to be used in cache By default it is 0, which means unlimited.
func MaxKeys ¶
MaxKeys functional option defines how many keys to keep. By default it is 0, which means unlimited.
func MaxValSize ¶
MaxValSize functional option defines the largest value's size allowed to be cached By default it is 0, which means unlimited.
type RedisCache ¶ added in v0.4.0
type RedisCache struct { CacheStat // contains filtered or unexported fields }
RedisCache implements LoadingCache for Redis.
func NewRedisCache ¶ added in v0.4.0
func NewRedisCache(backend *redis.Client, opts ...Option) (*RedisCache, error)
NewRedisCache makes Redis LoadingCache implementation.
func (*RedisCache) Close ¶ added in v0.6.0
func (c *RedisCache) Close() error
Close closes underlying connections
func (*RedisCache) Delete ¶ added in v0.4.0
func (c *RedisCache) Delete(key string)
Delete cache item by key
func (*RedisCache) Get ¶ added in v0.4.0
func (c *RedisCache) Get(key string, fn func() (interface{}, error)) (data interface{}, err error)
Get gets value by key or load with fn if not found in cache
func (*RedisCache) Invalidate ¶ added in v0.4.0
func (c *RedisCache) Invalidate(fn func(key string) bool)
Invalidate removes keys with passed predicate fn, i.e. fn(key) should be true to get evicted
func (*RedisCache) Keys ¶ added in v0.5.0
func (c *RedisCache) Keys() (res []string)
Keys gets all keys for the cache
func (*RedisCache) Peek ¶ added in v0.4.0
func (c *RedisCache) Peek(key string) (interface{}, bool)
Peek returns the key value (or undefined if not found) without updating the "recently used"-ness of the key.
func (*RedisCache) Purge ¶ added in v0.4.0
func (c *RedisCache) Purge()
Purge clears the cache completely.
func (*RedisCache) Stat ¶ added in v0.4.0
func (c *RedisCache) Stat() CacheStat
Stat returns cache statistics
type Scache ¶ added in v0.5.0
type Scache struct {
// contains filtered or unexported fields
}
Scache wraps LoadingCache with partitions (sub-system), and scopes. Simplified interface with just 4 funcs - Get, Flush, Stats and Close
Example ¶
LruCache illustrates the use of LRU loading cache
// set up test server for single response var hitCount int ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.String() == "/post/42" && hitCount == 0 { _, _ = w.Write([]byte("<html><body>test response</body></html>")) return } w.WriteHeader(404) })) // load page function loadURL := func(url string) ([]byte, error) { resp, err := http.Get(url) // nolint if err != nil { return nil, err } b, err := io.ReadAll(resp.Body) _ = resp.Body.Close() if err != nil { return nil, err } return b, nil } // fixed size LRU cache, 100 items, up to 10k in total size backend, err := NewLruCache(MaxKeys(100), MaxCacheSize(10*1024)) if err != nil { log.Fatalf("can't make lru cache, %v", err) } cache := NewScache(backend) // url not in cache, load data url := ts.URL + "/post/42" key := NewKey().ID(url).Scopes("test") val, err := cache.Get(key, func() (val []byte, err error) { return loadURL(url) }) if err != nil { log.Fatalf("can't load url %s, %v", url, err) } fmt.Println(string(val)) // url not in cache, load data key = NewKey().ID(url).Scopes("test") val, err = cache.Get(key, func() (val []byte, err error) { return loadURL(url) }) if err != nil { log.Fatalf("can't load url %s, %v", url, err) } fmt.Println(string(val)) // url cached, skip load and get from the cache key = NewKey().ID(url).Scopes("test") val, err = cache.Get(key, func() (val []byte, err error) { return loadURL(url) }) if err != nil { log.Fatalf("can't load url %s, %v", url, err) } fmt.Println(string(val)) // get cache stats stats := cache.Stat() fmt.Printf("%+v\n", stats) // close cache and test HTTP server after all log.Fatalf are passed ts.Close() err = cache.Close() if err != nil { log.Fatalf("can't close cache %v", err) }
Output: <html><body>test response</body></html> <html><body>test response</body></html> <html><body>test response</body></html> {hits:2, misses:1, ratio:0.67, keys:1, size:0, errors:0}
func NewScache ¶ added in v0.5.0
func NewScache(lc LoadingCache) *Scache
NewScache creates Scache on top of LoadingCache
func (*Scache) Flush ¶ added in v0.5.0
func (m *Scache) Flush(req FlusherRequest)
Flush clears cache and calls postFlushFn async
Source Files
¶
Directories
¶
Path | Synopsis |
---|---|
Package eventbus provides PubSub interface used for distributed cache invalidation, as well as NopPubSub and RedisPubSub implementations.
|
Package eventbus provides PubSub interface used for distributed cache invalidation, as well as NopPubSub and RedisPubSub implementations. |
internal
|
|
cache
Package cache implements LoadingCache.
|
Package cache implements LoadingCache. |