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 }