mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
server: Add global LRU for routes with keys being the appname + path (#472)
* Add global lru for routes with keys being the appname + path * minor comment fixes * remove duplicate entires from THIRD_PARTY * Make sure that we lock and unlock on get, refresh and delete on the cache
This commit is contained in:
committed by
C Cirello
parent
b8d01817b8
commit
6f8e94629f
88
api/server/internal/routecache/lru.go
Normal file
88
api/server/internal/routecache/lru.go
Normal file
@@ -0,0 +1,88 @@
|
||||
// Package routecache is meant to assist in resolving the most used routes at
|
||||
// an application. Implemented as a LRU, it returns always its full context for
|
||||
// iteration at the router handler.
|
||||
package routecache
|
||||
|
||||
// based on groupcache's LRU
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
|
||||
"github.com/iron-io/functions/api/models"
|
||||
)
|
||||
|
||||
// Cache holds an internal linkedlist for hotness management. It is not safe
|
||||
// for concurrent use, must be guarded externally.
|
||||
type Cache struct {
|
||||
MaxEntries int
|
||||
|
||||
ll *list.List
|
||||
cache map[string]*list.Element
|
||||
}
|
||||
|
||||
// New returns a route cache.
|
||||
func New(maxentries int) *Cache {
|
||||
return &Cache{
|
||||
MaxEntries: maxentries,
|
||||
ll: list.New(),
|
||||
cache: make(map[string]*list.Element),
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh updates internal linkedlist either adding a new route to the front,
|
||||
// or moving it to the front when used. It will discard seldom used routes.
|
||||
func (c *Cache) Refresh(route *models.Route) {
|
||||
if c.cache == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if ee, ok := c.cache[route.AppName+route.Path]; ok {
|
||||
c.ll.MoveToFront(ee)
|
||||
ee.Value = route
|
||||
return
|
||||
}
|
||||
|
||||
ele := c.ll.PushFront(route)
|
||||
c.cache[route.AppName+route.Path] = ele
|
||||
if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries {
|
||||
c.removeOldest()
|
||||
}
|
||||
}
|
||||
|
||||
// Get looks up a path's route from the cache.
|
||||
func (c *Cache) Get(appname, path string) (route *models.Route, ok bool) {
|
||||
if c.cache == nil {
|
||||
return
|
||||
}
|
||||
if ele, hit := c.cache[appname+path]; hit {
|
||||
c.ll.MoveToFront(ele)
|
||||
return ele.Value.(*models.Route), true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Delete removes the element for the given appname and path from the cache.
|
||||
func (c *Cache) Delete(appname, path string) {
|
||||
if ele, hit := c.cache[appname+path]; hit {
|
||||
c.removeElement(ele)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) removeOldest() {
|
||||
if c.cache == nil {
|
||||
return
|
||||
}
|
||||
if ele := c.ll.Back(); ele != nil {
|
||||
c.removeElement(ele)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) removeElement(e *list.Element) {
|
||||
c.ll.Remove(e)
|
||||
kv := e.Value.(*models.Route)
|
||||
delete(c.cache, kv.AppName+kv.Path)
|
||||
}
|
||||
|
||||
func (c *Cache) Len() int {
|
||||
return len(c.cache)
|
||||
}
|
||||
Reference in New Issue
Block a user