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)} }