fork of whitequark.org/git-pages with mods for tangled
at main 2.6 kB view raw
1package git_pages 2 3import ( 4 "context" 5 "time" 6 7 "github.com/maypok86/otter/v2" 8 "github.com/prometheus/client_golang/prometheus" 9) 10 11type weightedCacheEntry interface { 12 Weight() uint32 13} 14 15type trackedLoader[K comparable, V any] struct { 16 loader otter.Loader[K, V] 17 loaded bool 18 reloaded bool 19} 20 21func (l *trackedLoader[K, V]) Load(ctx context.Context, key K) (V, error) { 22 val, err := l.loader.Load(ctx, key) 23 l.loaded = true 24 return val, err 25} 26 27func (l *trackedLoader[K, V]) Reload(ctx context.Context, key K, oldValue V) (V, error) { 28 val, err := l.loader.Reload(ctx, key, oldValue) 29 l.reloaded = true 30 return val, err 31} 32 33type observedCacheMetrics struct { 34 HitNumberCounter prometheus.Counter 35 HitWeightCounter prometheus.Counter 36 MissNumberCounter prometheus.Counter 37 MissWeightCounter prometheus.Counter 38 EvictionNumberCounter prometheus.Counter 39 EvictionWeightCounter prometheus.Counter 40} 41 42type observedCache[K comparable, V weightedCacheEntry] struct { 43 Cache *otter.Cache[K, V] 44 45 metrics observedCacheMetrics 46} 47 48func newObservedCache[K comparable, V weightedCacheEntry]( 49 options *otter.Options[K, V], 50 metrics observedCacheMetrics, 51) (*observedCache[K, V], error) { 52 c := &observedCache[K, V]{} 53 c.metrics = metrics 54 55 optionsCopy := *options 56 options = &optionsCopy 57 options.StatsRecorder = c 58 59 var err error 60 c.Cache, err = otter.New(options) 61 if err != nil { 62 return nil, err 63 } 64 return c, nil 65} 66 67func (c *observedCache[K, V]) Get(ctx context.Context, key K, loader otter.Loader[K, V]) (V, error) { 68 observedLoader := trackedLoader[K, V]{loader: loader} 69 val, err := c.Cache.Get(ctx, key, &observedLoader) 70 if err == nil { 71 if observedLoader.loaded { 72 if c.metrics.MissNumberCounter != nil { 73 c.metrics.MissNumberCounter.Inc() 74 } 75 if c.metrics.MissWeightCounter != nil { 76 c.metrics.MissWeightCounter.Add(float64(val.Weight())) 77 } 78 } else { 79 if c.metrics.HitNumberCounter != nil { 80 c.metrics.HitNumberCounter.Inc() 81 } 82 if c.metrics.HitWeightCounter != nil { 83 c.metrics.HitWeightCounter.Add(float64(val.Weight())) 84 } 85 } 86 } 87 return val, err 88} 89 90func (c *observedCache[K, V]) RecordHits(count int) {} 91func (c *observedCache[K, V]) RecordMisses(count int) {} 92func (c *observedCache[K, V]) RecordEviction(weight uint32) { 93 if c.metrics.EvictionNumberCounter != nil { 94 c.metrics.EvictionNumberCounter.Inc() 95 } 96 if c.metrics.EvictionWeightCounter != nil { 97 c.metrics.EvictionWeightCounter.Add(float64(weight)) 98 } 99} 100func (c *observedCache[K, V]) RecordLoadSuccess(loadTime time.Duration) {} 101func (c *observedCache[K, V]) RecordLoadFailure(loadTime time.Duration) {}