Documentation
¶
Overview ¶
Package loadingcache provides a way for clients to create a cache capable of loading values on demand, should they get cache misses.
You can configure the cache to expire entries after a certain amount elapses since the last write and/or read.
This project is heavily inspired by Guava Cache (https://github.com/google/guava/wiki/CachesExplained).
All errors are wrapped by github.com/pkg/errors.Wrap. If you which to check the type of it, please use github.com/pkg/errors.Is.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrAlreadySet = errors.New("Cache already set")
ErrAlreadySet can be returned by Loader to tell the caller that the cache had already been set by its self.
var ErrKeyNotFound = errors.New("Key not found")
ErrKeyNotFound represents an error indicating that the key was not found
var StringFnvHashCodeFunc = func(k any) int { h := fnv.New32a() if _, err := h.Write([]byte(k.(string))); err != nil { panic(err) } return int(h.Sum32()) }
StringFnvHashCodeFunc is a hash code function for strings which uses fnv.New32a
Functions ¶
This section is empty.
Types ¶
type Cache ¶
type Cache interface { // Get returns the value associated with a given key. If no entry exists for // the provided key, loadingcache.ErrKeyNotFound is returned. Get(key any, options ...GetOption) (any, error) // Put adds a value to the cache identified by a key. // If a value already exists associated with that key, it // is replaced. Put(key, value any) // Invalidate removes keys from the cache. If a key does not exist it is a noop. Invalidate(keys ...any) // InvalidateAll invalidates all keys InvalidateAll() // Close cleans up any resources used by the cache Close() // Stats returns the current stats Stats() Stats // IsSharded tells the implementation is a sharded cache for testing. IsSharded() bool }
Cache describe the base interface to interact with a generic cache.
This interface reduces all keys and values to a generic any.
Example (AdvancedUsage) ¶
package main import ( "fmt" "time" "github.com/goldstd/loadingcache" ) func main() { cache := loadingcache.Config{ MaxSize: 2, ExpireAfterRead: 2 * time.Minute, ExpireAfterWrite: time.Minute, EvictListeners: []loadingcache.RemovalListener{ func(notification loadingcache.EvictNotification) { fmt.Printf("Entry removed due to %s\n", notification.Reason) }, }, Load: loadingcache.LoadFunc(func(key any, _ loadingcache.Cache) (any, error) { fmt.Printf("Loading key %v\n", key) return fmt.Sprint(key), nil }), }.Build() cache.Put(1, "1") val1, _ := cache.Get(1) fmt.Printf("%v\n", val1) val2, _ := cache.Get(2) fmt.Printf("%v\n", val2) val3, _ := cache.Get(3) fmt.Printf("%v\n", val3) }
Output: 1 Loading key 2 2 Loading key 3 Entry removed due to Size 3
Example (SimpleUsage) ¶
package main import ( "fmt" "github.com/goldstd/loadingcache" "github.com/pkg/errors" ) func main() { cache := loadingcache.Config{}.Build() // Adding some values and reading them cache.Put("a", 1) cache.Put("b", 2) cache.Put("c", 3) val1, _ := cache.Get("a") // Don't forget to check for errors fmt.Printf("%v\n", val1) val2, _ := cache.Get("b") // Don't forget to check for errors fmt.Printf("%v\n", val2) // Getting a value that does not exist _, err := cache.Get("d") if errors.Is(err, loadingcache.ErrKeyNotFound) { fmt.Println("That key does not exist") } // Evicting cache.Invalidate("a") cache.Invalidate("b", "c") cache.InvalidateAll() }
Output: 1 2 That key does not exist
type CacheOption ¶
type CacheOption func(Cache)
CacheOption describes an option that can configure the cache
type Config ¶
type Config struct { // Clock allows passing a custom clock to be used with the cache. // // This is useful for testing, where controlling time is important. Clock clock.Clock // Load configures a loading function Load Loader // ShardHashFunc is a function that produces a hashcode of the key. // // See https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/Object.html#hashCode() // for best practices surrounding hash code functions. ShardHashFunc func(key any) int // EvictListeners configures a removal listeners EvictListeners []RemovalListener // ExpireAfterWrite configures the cache to expire entries after // a given duration after writing. ExpireAfterWrite time.Duration // ExpireAfterRead configures the cache to expire entries after // a given duration after reading. ExpireAfterRead time.Duration // EvictInterval controls if a background go routine should be created // which automatically evicts entries that have expired. If not specified, // no background goroutine will be created. // // The background go routine runs with the provided frequency. // To avoid go routine leaks, use the close function when you're done with the cache. EvictInterval time.Duration // MaxSize limits the number of entries allowed in the cache. // If the limit is achieved, an eviction process will take place, // this means that eviction policies will be executed such as write // time, read time or random entry if no eviction policy frees up // space. // // If the cache is sharded, MaxSize is applied to each shard, // meaning that the overall capacity will be MaxSize * ShardCount. MaxSize uint32 // ShardCount indicates how many shards will be used by the cache. // This allows some degree of parallelism in read and writing to the cache. // // If the shard count is greater than 1, then ShardHashFunc must be provided // otherwise the constructor will panic. ShardCount uint32 // AsyncLoad configures loading in async way after cache expired AsyncLoad bool }
Config available options to initialize the cache
type EvictNotification ¶
type EvictNotification struct { Key any Value any Reason EvictReason }
EvictNotification is passed to listeners everytime an entry is removed
type EvictReason ¶
type EvictReason int
EvictReason is an enum describing the causes for an entry to be removed from the cache.
const ( // EvictReasonExplicit means the entry was explicitly invalidated EvictReasonExplicit EvictReason = iota // EvictReasonReplaced means the entry was replaced by a new one EvictReasonReplaced // EvictReasonReadExpired means the entry read expired, e.g. too much time // since last read/write. EvictReasonReadExpired // EvictReasonWriteExpired means the entry write expired, e.g. too much time // since last read/write. EvictReasonWriteExpired // EvictReasonSize means the entry was removed due to the cache size. EvictReasonSize )
func (EvictReason) String ¶
func (r EvictReason) String() string
type Loader ¶
type Loader interface { // Load loads the latest value by the key. // err can be ErrAlreadySet to indicate that the loader had been set the cache. Load(key any, cache Cache) (any, error) }
Loader represents an interface for loading cache value.
type RemovalListener ¶
type RemovalListener func(EvictNotification)
RemovalListener represents a removal listener
type Stats ¶
type Stats interface { // EvictionCount is the number of times an entry has been evicted EvictionCount() int64 // HitCount the number of times Cache lookup methods have returned a cached value HitCount() int64 // HitRate is the ratio of cache requests which were hits. This is defined as // hitCount / requestCount, or 1.0 when requestCount == 0 HitRate() float64 // MissCount is the number of times Cache lookup methods have returned an uncached // (newly loaded) value MissCount() int64 // MissRate is the ratio of cache requests which were misses. This is defined as // missCount / requestCount, or 0.0 when requestCount == 0 MissRate() float64 // RequestCount is the number of times Cache lookup methods have returned either a cached or // uncached value. This is defined as hitCount + missCount RequestCount() int64 // LoadSuccessCount is the number of times Cache lookup methods have successfully // loaded a new value LoadSuccessCount() int64 // LoadErrorCount is the number of times Cache lookup methods threw an exception while loading // a new value LoadErrorCount() int64 // LoadErrorRate is the ratio of cache loading attempts which threw exceptions. // This is defined as loadExceptionCount / (loadSuccessCount + loadExceptionCount), or 0.0 when // loadSuccessCount + loadExceptionCount == 0 LoadErrorRate() float64 // LoadCount the total number of times that Cache lookup methods attempted to load new values. // This includes both successful load operations, and those that threw exceptions. // This is defined as loadSuccessCount + loadExceptionCount LoadCount() int64 // LoadTotalTime is the total duration the cache has spent loading new values LoadTotalTime() time.Duration // AverageLoadPenalty is the average duration spent loading new values. This is defined as // totalLoadTime / (loadSuccessCount + loadExceptionCount). AverageLoadPenalty() time.Duration }
Stats exposes cache relevant metrics.
Be aware that this interface may be exposing a live stats collector, and as such if you manually calculate rates, values may differ if calls to the cache have occurred between calls.