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 }