github.com/haraldrudell/parl@v0.4.176/counter/cached-counters.go (about) 1 /* 2 © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package counter 7 8 import ( 9 "github.com/haraldrudell/parl" 10 "github.com/haraldrudell/parl/perrors" 11 ) 12 13 // CachedCounters reduces counter map contention by only looking up the counterID once 14 type CachedCounters struct { 15 counterStore parl.CounterStore // uncached counters accessible by ID 16 counterValues map[parl.CounterID]parl.CounterValues // cached regular counters 17 rateCounterValues map[parl.CounterID]parl.RateCounterValues // cached rate counters 18 datapointValue map[parl.CounterID]parl.DatapointValue // cached datapoints 19 } 20 21 // NewCachedCounters returns a cache of parl.CounterID reducing map contention 22 func NewCachedCounters(counterStore parl.CounterStore) (cachedCounters *CachedCounters) { 23 return &CachedCounters{ 24 counterStore: counterStore, 25 counterValues: make(map[parl.CounterID]parl.CounterValues), 26 rateCounterValues: make(map[parl.CounterID]parl.RateCounterValues), 27 datapointValue: make(map[parl.CounterID]parl.DatapointValue), 28 } 29 } 30 31 // CounterValues never returns nil 32 // - returns consumer interface for regular counter: Get and Value methods 33 func (c *CachedCounters) CounterValues(counterID parl.CounterID) (counterValues parl.CounterValues) { 34 35 // try cached value 36 if counterValues = c.counterValues[counterID]; counterValues != nil { 37 return 38 } 39 40 // populate cache 41 42 // counter is the provider interface of a regular counter, 43 // what is returned by GetOrCreateCounter 44 var counter = c.counterStore.GetCounter(counterID) 45 counterValues = counter.(parl.CounterValues) 46 c.counterValues[counterID] = counterValues 47 48 return 49 } 50 51 // RateCounter may return nil 52 // - returns consumer interface for rate counter: Get Value Rates methods 53 func (c *CachedCounters) RateCounter(counterID parl.CounterID) (rateCounterValues parl.RateCounterValues) { 54 55 // try cached value 56 if rateCounterValues = c.rateCounterValues[counterID]; rateCounterValues != nil { 57 return 58 } 59 60 // populate cache 61 var counterAny any 62 var ok bool 63 if counterAny = c.counterStore.GetNamedCounter(counterID); counterAny == nil { 64 return 65 } else if rateCounterValues, ok = counterAny.(parl.RateCounterValues); !ok { 66 panic(perrors.ErrorfPF("not a rate counter: counter ID: %s type: %T", counterID, counterAny)) 67 } 68 c.rateCounterValues[counterID] = rateCounterValues 69 70 return 71 } 72 73 // RateCounter may return nil 74 // - returns consumer interface for rate counter: Get Value Rates methods 75 func (c *CachedCounters) DataPoint(counterID parl.CounterID) (datapointValue parl.DatapointValue) { 76 77 // try cached value 78 if datapointValue = c.datapointValue[counterID]; datapointValue != nil { 79 return 80 } 81 82 // populate cache 83 var counterAny any 84 var ok bool 85 if counterAny = c.counterStore.GetNamedCounter(counterID); counterAny == nil { 86 return 87 } else if datapointValue, ok = counterAny.(parl.DatapointValue); !ok { 88 panic(perrors.ErrorfPF("not a datapoint: counter ID: %s type: %t", counterID, counterAny)) 89 } 90 c.datapointValue[counterID] = datapointValue 91 92 return 93 }