github.com/iron-io/functions@v0.0.0-20180820112432-d59d7d1c40b2/api/server/internal/routecache/lru.go (about)

     1  // Package routecache is meant to assist in resolving the most used routes at
     2  // an application. Implemented as a LRU, it returns always its full context for
     3  // iteration at the router handler.
     4  package routecache
     5  
     6  // based on groupcache's LRU
     7  
     8  import (
     9  	"container/list"
    10  
    11  	"github.com/iron-io/functions/api/models"
    12  )
    13  
    14  // Cache holds an internal linkedlist for hotness management. It is not safe
    15  // for concurrent use, must be guarded externally.
    16  type Cache struct {
    17  	MaxEntries int
    18  
    19  	ll    *list.List
    20  	cache map[string]*list.Element
    21  }
    22  
    23  // New returns a route cache.
    24  func New(maxentries int) *Cache {
    25  	return &Cache{
    26  		MaxEntries: maxentries,
    27  		ll:         list.New(),
    28  		cache:      make(map[string]*list.Element),
    29  	}
    30  }
    31  
    32  // Refresh updates internal linkedlist either adding a new route to the front,
    33  // or moving it to the front when used. It will discard seldom used routes.
    34  func (c *Cache) Refresh(route *models.Route) {
    35  	if c.cache == nil {
    36  		return
    37  	}
    38  
    39  	if ee, ok := c.cache[route.AppName+route.Path]; ok {
    40  		c.ll.MoveToFront(ee)
    41  		ee.Value = route
    42  		return
    43  	}
    44  
    45  	ele := c.ll.PushFront(route)
    46  	c.cache[route.AppName+route.Path] = ele
    47  	if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries {
    48  		c.removeOldest()
    49  	}
    50  }
    51  
    52  // Get looks up a path's route from the cache.
    53  func (c *Cache) Get(appname, path string) (route *models.Route, ok bool) {
    54  	if c.cache == nil {
    55  		return
    56  	}
    57  	if ele, hit := c.cache[appname+path]; hit {
    58  		c.ll.MoveToFront(ele)
    59  		return ele.Value.(*models.Route), true
    60  	}
    61  	return
    62  }
    63  
    64  // Delete removes the element for the given appname and path from the cache.
    65  func (c *Cache) Delete(appname, path string) {
    66  	if ele, hit := c.cache[appname+path]; hit {
    67  		c.removeElement(ele)
    68  	}
    69  }
    70  
    71  func (c *Cache) removeOldest() {
    72  	if c.cache == nil {
    73  		return
    74  	}
    75  	if ele := c.ll.Back(); ele != nil {
    76  		c.removeElement(ele)
    77  	}
    78  }
    79  
    80  func (c *Cache) removeElement(e *list.Element) {
    81  	c.ll.Remove(e)
    82  	kv := e.Value.(*models.Route)
    83  	delete(c.cache, kv.AppName+kv.Path)
    84  }
    85  
    86  func (c *Cache) Len() int {
    87  	return len(c.cache)
    88  }