lru

package
v0.0.0-...-4dd3b10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 24, 2019 License: MIT Imports: 7 Imported by: 0

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

View Source
const (
	// LRUEviction denotes an item was evicted via LRU
	LRUEviction = iota
	// TTLEviction denotes an item was evicted via TTL
	TTLEviction
)

Variables

View Source
var ErrExists = errors.New("item exists")

ErrExists is the error returned when an item exists.

View Source
var ErrNotFound = errors.New("item not found")

ErrNotFound is the error returned when a value isn't found.

Functions

func BytesToUint64

func BytesToUint64(b []byte) (uint64, error)

BytesToUint64 is a helper to convert a byte slice to a uint64.

func Uint64ToBytes

func Uint64ToBytes(n uint64) []byte

Uint64ToBytes is a helper to convert a uint64 to a byte slice.

Types

type Cache

type Cache struct {
	sync.Mutex
	// contains filtered or unexported fields
}

Cache is an LRU+TTL cache

func New

func New(maxEntries int) *Cache

New creates a new Cache and initializes the various internal items.

func (*Cache) Add

func (c *Cache) Add(key string, value []byte, ttl time.Duration) error

Add sets the item only if it doesn't already exist.

func (*Cache) Append

func (c *Cache) Append(key string, value []byte, ttl time.Duration) error

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

func (c *Cache) Cas(key string, value []byte, ttl time.Duration, cas uint64) error

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

func (c *Cache) Decrement(key string, decrementBy uint64) error

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) Delete

func (c *Cache) Delete(key string)

Delete deletes the item from the cache.

func (*Cache) FlushAll

func (c *Cache) FlushAll()

FlushAll removes all items from the cache.

func (*Cache) Get

func (c *Cache) Get(key string) ([]byte, error)

Get gets the value for the given key.

func (*Cache) Gets

func (c *Cache) Gets(key string) ([]byte, uint64, error)

Gets gets the value for the given key and also returns the value's CAS ID.

func (*Cache) Increment

func (c *Cache) Increment(key string, incrementBy uint64) error

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

func (c *Cache) Prepend(key string, value []byte, ttl time.Duration) error

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) Replace

func (c *Cache) Replace(key string, value []byte, ttl time.Duration) error

Replace only sets the item if it does already exist.

func (*Cache) Set

func (c *Cache) Set(key string, value []byte, ttl time.Duration)

Set unconditionally sets the item, potentially overwriting a previous value and moving the item to the top of the LRU.

func (*Cache) Touch

func (c *Cache) Touch(key string, ttl time.Duration) error

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL