predictor/internal/windviz/cache.go

63 lines
1.5 KiB
Go

package windviz
import (
"sync"
"time"
)
// Cache is a small bounded cache of rasterized fields keyed by request
// parameters and dataset epoch. It is safe for concurrent use.
//
// Visualization requests repeat heavily (a frontend re-fetches the same
// layer as users pan within a tile), so even a tiny cache removes most
// recomputation. Eviction is simplest-possible: when full, the whole map is
// cleared. Entries also expire after TTL.
type Cache struct {
mu sync.Mutex
entries map[string]cacheEntry
max int
ttl time.Duration
now func() time.Time
}
type cacheEntry struct {
field Field
expires time.Time
}
// NewCache returns a cache holding up to max entries for ttl each.
func NewCache(max int, ttl time.Duration) *Cache {
if max <= 0 {
max = 64
}
if ttl <= 0 {
ttl = 10 * time.Minute
}
return &Cache{
entries: make(map[string]cacheEntry, max),
max: max,
ttl: ttl,
now: time.Now,
}
}
// Get returns the cached field for key, if present and unexpired.
func (c *Cache) Get(key string) (Field, bool) {
c.mu.Lock()
defer c.mu.Unlock()
e, ok := c.entries[key]
if !ok || c.now().After(e.expires) {
return nil, false
}
return e.field, true
}
// Put stores field under key.
func (c *Cache) Put(key string, field Field) {
c.mu.Lock()
defer c.mu.Unlock()
if len(c.entries) >= c.max {
c.entries = make(map[string]cacheEntry, c.max)
}
c.entries[key] = cacheEntry{field: field, expires: c.now().Add(c.ttl)}
}