github.com/maypok86/otter@v1.2.1/cache.go (about) 1 // Copyright (c) 2024 Alexey Mayshev. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package otter 16 17 import ( 18 "time" 19 20 "github.com/maypok86/otter/internal/core" 21 ) 22 23 // DeletionCause the cause why a cached entry was deleted. 24 type DeletionCause = core.DeletionCause 25 26 const ( 27 // Explicit the entry was manually deleted by the user. 28 Explicit = core.Explicit 29 // Replaced the entry itself was not actually deleted, but its value was replaced by the user. 30 Replaced = core.Replaced 31 // Size the entry was evicted due to size constraints. 32 Size = core.Size 33 // Expired the entry's expiration timestamp has passed. 34 Expired = core.Expired 35 ) 36 37 type baseCache[K comparable, V any] struct { 38 cache *core.Cache[K, V] 39 } 40 41 func newBaseCache[K comparable, V any](c core.Config[K, V]) baseCache[K, V] { 42 return baseCache[K, V]{ 43 cache: core.NewCache(c), 44 } 45 } 46 47 // Has checks if there is an entry with the given key in the cache. 48 func (bs baseCache[K, V]) Has(key K) bool { 49 return bs.cache.Has(key) 50 } 51 52 // Get returns the value associated with the key in this cache. 53 func (bs baseCache[K, V]) Get(key K) (V, bool) { 54 return bs.cache.Get(key) 55 } 56 57 // Delete removes the association for this key from the cache. 58 func (bs baseCache[K, V]) Delete(key K) { 59 bs.cache.Delete(key) 60 } 61 62 // DeleteByFunc removes the association for this key from the cache when the given function returns true. 63 func (bs baseCache[K, V]) DeleteByFunc(f func(key K, value V) bool) { 64 bs.cache.DeleteByFunc(f) 65 } 66 67 // Range iterates over all entries in the cache. 68 // 69 // Iteration stops early when the given function returns false. 70 func (bs baseCache[K, V]) Range(f func(key K, value V) bool) { 71 bs.cache.Range(f) 72 } 73 74 // Clear clears the hash table, all policies, buffers, etc. 75 // 76 // NOTE: this operation must be performed when no requests are made to the cache otherwise the behavior is undefined. 77 func (bs baseCache[K, V]) Clear() { 78 bs.cache.Clear() 79 } 80 81 // Close clears the hash table, all policies, buffers, etc and stop all goroutines. 82 // 83 // NOTE: this operation must be performed when no requests are made to the cache otherwise the behavior is undefined. 84 func (bs baseCache[K, V]) Close() { 85 bs.cache.Close() 86 } 87 88 // Size returns the current number of entries in the cache. 89 func (bs baseCache[K, V]) Size() int { 90 return bs.cache.Size() 91 } 92 93 // Capacity returns the cache capacity. 94 func (bs baseCache[K, V]) Capacity() int { 95 return bs.cache.Capacity() 96 } 97 98 // Stats returns a current snapshot of this cache's cumulative statistics. 99 func (bs baseCache[K, V]) Stats() Stats { 100 return newStats(bs.cache.Stats()) 101 } 102 103 // Extension returns access to inspect and perform low-level operations on this cache based on its runtime 104 // characteristics. These operations are optional and dependent on how the cache was constructed 105 // and what abilities the implementation exposes. 106 func (bs baseCache[K, V]) Extension() Extension[K, V] { 107 return newExtension(bs.cache) 108 } 109 110 // Cache is a structure performs a best-effort bounding of a hash table using eviction algorithm 111 // to determine which entries to evict when the capacity is exceeded. 112 type Cache[K comparable, V any] struct { 113 baseCache[K, V] 114 } 115 116 func newCache[K comparable, V any](c core.Config[K, V]) Cache[K, V] { 117 return Cache[K, V]{ 118 baseCache: newBaseCache(c), 119 } 120 } 121 122 // Set associates the value with the key in this cache. 123 // 124 // If it returns false, then the key-value pair had too much cost and the Set was dropped. 125 func (c Cache[K, V]) Set(key K, value V) bool { 126 return c.cache.Set(key, value) 127 } 128 129 // SetIfAbsent if the specified key is not already associated with a value associates it with the given value. 130 // 131 // If the specified key is not already associated with a value, then it returns false. 132 // 133 // Also, it returns false if the key-value pair had too much cost and the SetIfAbsent was dropped. 134 func (c Cache[K, V]) SetIfAbsent(key K, value V) bool { 135 return c.cache.SetIfAbsent(key, value) 136 } 137 138 // CacheWithVariableTTL is a structure performs a best-effort bounding of a hash table using eviction algorithm 139 // to determine which entries to evict when the capacity is exceeded. 140 type CacheWithVariableTTL[K comparable, V any] struct { 141 baseCache[K, V] 142 } 143 144 func newCacheWithVariableTTL[K comparable, V any](c core.Config[K, V]) CacheWithVariableTTL[K, V] { 145 return CacheWithVariableTTL[K, V]{ 146 baseCache: newBaseCache(c), 147 } 148 } 149 150 // Set associates the value with the key in this cache and sets the custom ttl for this key-value pair. 151 // 152 // If it returns false, then the key-value pair had too much cost and the Set was dropped. 153 func (c CacheWithVariableTTL[K, V]) Set(key K, value V, ttl time.Duration) bool { 154 return c.cache.SetWithTTL(key, value, ttl) 155 } 156 157 // SetIfAbsent if the specified key is not already associated with a value associates it with the given value 158 // and sets the custom ttl for this key-value pair. 159 // 160 // If the specified key is not already associated with a value, then it returns false. 161 // 162 // Also, it returns false if the key-value pair had too much cost and the SetIfAbsent was dropped. 163 func (c CacheWithVariableTTL[K, V]) SetIfAbsent(key K, value V, ttl time.Duration) bool { 164 return c.cache.SetIfAbsentWithTTL(key, value, ttl) 165 }