bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/bosun/cache/cache.go (about) 1 package cache // import "bosun.org/cmd/bosun/cache" 2 3 import ( 4 "sync" 5 6 "github.com/golang/groupcache/lru" 7 "github.com/golang/groupcache/singleflight" 8 ) 9 10 type Cache struct { 11 g singleflight.Group 12 13 sync.Mutex 14 lru *lru.Cache 15 Name string 16 } 17 18 // New creates a new LRU cache of the request length with 19 // an exported Name for instrumentation 20 func New(name string, MaxEntries int) *Cache { 21 return &Cache{ 22 lru: lru.New(MaxEntries), 23 Name: name, 24 } 25 } 26 27 // Get returns a cached value based on the passed key or runs the passed function to get the value 28 // if there is no corresponding value in the cache 29 func (c *Cache) Get(key string, getFn func() (interface{}, error)) (i interface{}, err error, hit bool) { 30 if c == nil { 31 i, err = getFn() 32 return 33 } 34 c.Lock() 35 result, ok := c.lru.Get(key) 36 c.Unlock() 37 if ok { 38 return result, nil, true 39 } 40 // our lock only serves to protect the lru. 41 // we can (and should!) do singleflight requests concurrently 42 i, err = c.g.Do(key, func() (interface{}, error) { 43 v, err := getFn() 44 if err == nil { 45 c.Lock() 46 c.lru.Add(key, v) 47 c.Unlock() 48 } 49 return v, err 50 }) 51 return 52 }