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  }