alice-lg/pkg/caches/routes.go
2021-07-05 16:21:12 +02:00

101 lines
2.0 KiB
Go

package caches
import (
"sync"
"time"
"github.com/alice-lg/alice-lg/pkg/api"
)
/*
RoutesCache stores routes responses from the backend.
Keep a kv map with neighborId <-> api.RoutesResponse
TTL is derived from the api.RoutesResponse.
To avoid memory issues, we only keep N responses (MRU) (per RS).
*/
type RoutesCache struct {
responses map[string]*api.RoutesResponse
accessedAt LRUMap
disabled bool
size int
sync.Mutex
}
// NewRoutesCache initializes a new cache for route responses.
func NewRoutesCache(disabled bool, size int) *RoutesCache {
cache := &RoutesCache{
responses: make(map[string]*api.RoutesResponse),
accessedAt: make(map[string]time.Time),
disabled: disabled,
size: size,
}
return cache
}
// Get retrievs all routes for a given neighbor
func (cache *RoutesCache) Get(neighborID string) *api.RoutesResponse {
if cache.disabled {
return nil
}
cache.Lock()
defer cache.Unlock()
response, ok := cache.responses[neighborID]
if !ok {
return nil
}
if response.CacheTTL() < 0 {
return nil
}
cache.accessedAt[neighborID] = time.Now()
return response
}
// Set the routes response for a given neighbor
func (cache *RoutesCache) Set(neighborID string, response *api.RoutesResponse) {
if cache.disabled {
return
}
cache.Lock()
defer cache.Unlock()
if len(cache.responses) > cache.size {
// delete LRU
leastRecentNeighbor := cache.accessedAt.LRU()
delete(cache.accessedAt, leastRecentNeighbor)
delete(cache.responses, leastRecentNeighbor)
}
cache.accessedAt[neighborID] = time.Now()
cache.responses[neighborID] = response
}
// Expire will flush expired keys. (TODO: naming could be better.)
func (cache *RoutesCache) Expire() int {
cache.Lock()
defer cache.Unlock()
expiredKeys := []string{}
for key, response := range cache.responses {
if response.CacheTTL() < 0 {
expiredKeys = append(expiredKeys, key)
}
}
for _, key := range expiredKeys {
delete(cache.responses, key)
}
return len(expiredKeys)
}