github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/pkg/cache/cache.go (about) 1 package cache 2 3 import ( 4 "time" 5 6 "github.com/dustin/go-humanize" 7 "github.com/rs/zerolog" 8 ) 9 10 // Config for caching. 11 // See: https://github.com/outcaste-io/ristretto#Config 12 type Config struct { 13 // NumCounters determines the number of counters (keys) to keep that hold 14 // access frequency information. It's generally a good idea to have more 15 // counters than the max cache capacity, as this will improve eviction 16 // accuracy and subsequent hit ratios. 17 // 18 // For example, if you expect your cache to hold 1,000,000 items when full, 19 // NumCounters should be 10,000,000 (10x). Each counter takes up roughly 20 // 3 bytes (4 bits for each counter * 4 copies plus about a byte per 21 // counter for the bloom filter). Note that the number of counters is 22 // internally rounded up to the nearest power of 2, so the space usage 23 // may be a little larger than 3 bytes * NumCounters. 24 NumCounters int64 25 26 // MaxCost can be considered as the cache capacity, in whatever units you 27 // choose to use. 28 // 29 // For example, if you want the cache to have a max capacity of 100MB, you 30 // would set MaxCost to 100,000,000 and pass an item's number of bytes as 31 // the `cost` parameter for calls to Set. If new items are accepted, the 32 // eviction process will take care of making room for the new item and not 33 // overflowing the MaxCost value. 34 MaxCost int64 35 36 // DefaultTTL configures a default deadline on the lifetime of any keys set 37 // to the cache. 38 DefaultTTL time.Duration 39 } 40 41 func (c *Config) MarshalZerologObject(e *zerolog.Event) { 42 e. 43 Str("maxCost", humanize.IBytes(uint64(c.MaxCost))). 44 Int64("numCounters", c.NumCounters). 45 Dur("defaultTTL", c.DefaultTTL) 46 } 47 48 // Cache defines an interface for a generic cache. 49 type Cache interface { 50 // Get returns the value for the given key in the cache, if it exists. 51 Get(key any) (any, bool) 52 53 // Set sets a value for the key in the cache, with the given cost. 54 Set(key, entry any, cost int64) bool 55 56 // Wait waits for the cache to process and apply updates. 57 Wait() 58 59 // Close closes the cache's background workers (if any). 60 Close() 61 62 // GetMetrics returns the metrics block for the cache. 63 GetMetrics() Metrics 64 65 zerolog.LogObjectMarshaler 66 } 67 68 // Metrics defines metrics exported by the cache. 69 type Metrics interface { 70 // Hits is the number of cache hits. 71 Hits() uint64 72 73 // Misses is the number of cache misses. 74 Misses() uint64 75 76 // CostAdded returns the total cost of added items. 77 CostAdded() uint64 78 79 // CostEvicted returns the total cost of evicted items. 80 CostEvicted() uint64 81 } 82 83 // NoopCache returns a cache that does nothing. 84 func NoopCache() Cache { return &noopCache{} } 85 86 type noopCache struct{} 87 88 var _ Cache = (*noopCache)(nil) 89 90 func (no *noopCache) Get(_ any) (any, bool) { return nil, false } 91 func (no *noopCache) Set(_, _ any, _ int64) bool { return false } 92 func (no *noopCache) Wait() {} 93 func (no *noopCache) Close() {} 94 func (no *noopCache) GetMetrics() Metrics { return &noopMetrics{} } 95 func (no *noopCache) MarshalZerologObject(e *zerolog.Event) { 96 e.Bool("enabled", false) 97 } 98 99 type noopMetrics struct{} 100 101 var _ Metrics = (*noopMetrics)(nil) 102 103 func (no *noopMetrics) Hits() uint64 { return 0 } 104 func (no *noopMetrics) Misses() uint64 { return 0 } 105 func (no *noopMetrics) CostAdded() uint64 { return 0 } 106 func (no *noopMetrics) CostEvicted() uint64 { return 0 }