Documentation
¶
Overview ¶
Package lru implements an LRU+TTL caching library that (mostly) follows the functions offered by memcached. It was initially based on groupcache/lru and evolved into a more fully featured library to support the back end caching needs of grpc-cache. Cache items are keyed with strings and valued with []byte. While interface{} values might be a bit more flexible, []byte was chosen for a few reasons. First, []byte aligns better with protobuf's byte type, though this library should be useful outside of that context. Second, it's relatively easy to encode/decode Go types into a []byte, and in fact common complex encoded types in Go use []byte natively (encoding/json, encoding/gob, etc). Third, the update functions (Increment/Decrement and Append/Prepend) are easier to write and test without resorting to reflection. For convenience, helpers are provided for encoding and decoding uint64 to/from []byte for counters.
This library employs two cache strategies: Least Recently Used (LRU) and Time To Live. LRU can be disabled globally by setting the maxEntries to 0:
myCache := lru.New(0)
TTL can be disabled on a per item basis by setting the ttl argument in the various set commands to 0: Otherwise, items will expire when the time.Duration
myCache.Set("blah", []byte("whatever"), time.Minutes*20)
has been reached and the item is accessed again ... note that timeouts are lazy, so items that are set and have timed out but aren't accessed will count towards the LRU max.
Note that this library is not thread safe. Locking has been left up to the caller. This allows, for exammple, more efficient batch operations because the library functions operate on a single value, but the caller could lock around a set of operations. In addition, it allows the caller to use their preferred method for assuring safe concurrent access. And finally, if the library is used in a single-threaded situation, locking unecessary locking won't needlessly impact performance. All that said, the Cache type conveniently embeds sync.Mutex so that a per instance lock is easy to use:
myCache.Lock() myCache.Set("thing", []byte("stuff"), 0) myCache.Unlock()
Note also that all operations read from and potentially write to internal data structures, so locking in a concurrent environment is necessary, even for Get/Gets.
Index ¶
- Constants
- Variables
- func BytesToUint64(b []byte) (uint64, error)
- func Uint64ToBytes(n uint64) []byte
- type Cache
- func (c *Cache) Add(key string, value []byte, ttl time.Duration) error
- func (c *Cache) Append(key string, value []byte, ttl time.Duration) error
- func (c *Cache) Cas(key string, value []byte, ttl time.Duration, cas uint64) error
- func (c *Cache) Decrement(key string, decrementBy uint64) error
- func (c *Cache) Delete(key string)
- func (c *Cache) FlushAll()
- func (c *Cache) Get(key string) ([]byte, error)
- func (c *Cache) Gets(key string) ([]byte, uint64, error)
- func (c *Cache) Increment(key string, incrementBy uint64) error
- func (c *Cache) Prepend(key string, value []byte, ttl time.Duration) error
- func (c *Cache) Replace(key string, value []byte, ttl time.Duration) error
- func (c *Cache) Set(key string, value []byte, ttl time.Duration)
- func (c *Cache) Touch(key string, ttl time.Duration) error
- func (c *Cache) WithEvictionHandler(h EvictionHandler) *Cache
- type EvictionHandler
- type EvictionHandlerFunc
- type EvictionReason
Constants ¶
const ( // LRUEviction denotes an item was evicted via LRU LRUEviction = iota // TTLEviction denotes an item was evicted via TTL TTLEviction )
Variables ¶
var ErrExists = errors.New("item exists")
ErrExists is the error returned when an item exists.
var ErrNotFound = errors.New("item not found")
ErrNotFound is the error returned when a value isn't found.
Functions ¶
func BytesToUint64 ¶
BytesToUint64 is a helper to convert a byte slice to a uint64.
func Uint64ToBytes ¶
Uint64ToBytes is a helper to convert a uint64 to a byte slice.
Types ¶
type Cache ¶
Cache is an LRU+TTL cache
func (*Cache) Append ¶
Append appends the given value to the currently stored value for the key. If the key doesn't currently exist (or has aged out) ErrNotFound is returned.
func (*Cache) Cas ¶
Cas is a "compare and swap" or "check and set" operation. It attempts to set the key/value pair if a) the item already exists in the cache and b) the item's current cas value matches the supplied argument. If the item doesn't exist, it returns ErrNotFound, and if the item exists but has a different cas value, it returns ErrExists. CAS is useful when multiple clients may be operating on the same cached items and updates should only be applied by one if a change hasn't occurred in the meantime by another.
func (*Cache) Decrement ¶
Decrement decrements the value of key by decrBy. The value should be stored as a uint64 converted to a []byte with Uint64ToBytes (or something equivalent) or the behavior is undefined.
func (*Cache) Increment ¶
Increment increments the value of key by incrementBy. The value should be stored as a uint64 converted to a []byte with Uint64ToBytes (or something equivalent) or the behavior is undefined.
func (*Cache) Prepend ¶
Prepend prepends the given value to the currently stored value for the key. If the key doesn't currently exist (or has aged out) ErrNotFound is returned.
func (*Cache) Set ¶
Set unconditionally sets the item, potentially overwriting a previous value and moving the item to the top of the LRU.
func (*Cache) Touch ¶
Touch updates the item's eviction status (LRU and TTL if supplied) and CAS ID without requiring the value. If the item doesn't already exist, it returns an ErrNotFound.
func (*Cache) WithEvictionHandler ¶
func (c *Cache) WithEvictionHandler(h EvictionHandler) *Cache
WithEvictionHandler attaches a callback that will be called whenever an item is evicted from the cache. Note that this will be called for LRU or TTL evictions but not for explicit calls to Delete.
type EvictionHandler ¶
type EvictionHandler interface {
HandleEviction(key string, value []byte, reason EvictionReason)
}
EvictionHandler is an interface for implementing a function to be called when an item is evicted from the cache.
type EvictionHandlerFunc ¶
type EvictionHandlerFunc func(key string, value []byte, reason EvictionReason)
EvictionHandlerFunc is a convenience type for EvictionHandler implementations.
func (EvictionHandlerFunc) HandleEviction ¶
func (h EvictionHandlerFunc) HandleEviction(key string, value []byte, reason EvictionReason)
HandleEviction implements the EvictionHandler interface.
type EvictionReason ¶
type EvictionReason int
EvictionReason encapsulates the reason for an eviction in an evictionHandler
func (EvictionReason) String ¶
func (e EvictionReason) String() string
String stringifies the EvictionReason