package indexer import ( "sync" "time" "github.com/rs/zerolog/log" ) type CacheEntry struct { Key string URL string Result SearchResult CreatedAt time.Time TTL time.Duration RefreshInterval time.Duration } func (e *CacheEntry) IsExpired() bool { return time.Now().After(e.CreatedAt.Add(e.TTL)) } type IndexerCache struct { entries map[string]*CacheEntry mu sync.RWMutex } func NewIndexerCache() *IndexerCache { return &IndexerCache{ entries: make(map[string]*CacheEntry), } } func (c *IndexerCache) Get(key string) (*CacheEntry, bool) { c.mu.RLock() defer c.mu.RUnlock() entry, ok := c.entries[key] if !ok { log.Trace().Str("key", key).Msg("cache miss") return nil, false } if entry.IsExpired() { log.Trace().Str("key", key).Msg("cache expired") return nil, false } log.Trace().Str("key", key).Int("items", len(entry.Result.Items)).Msg("cache hit") return entry, true } func (c *IndexerCache) Add(entry CacheEntry) { c.mu.Lock() defer c.mu.Unlock() c.entries[entry.Key] = &entry log.Debug().Str("key", entry.Key).Int("items", len(entry.Result.Items)).Dur("ttl", entry.TTL).Dur("refresh", entry.RefreshInterval).Msg("cache entry added") } func (c *IndexerCache) Update(key string, result SearchResult) { c.mu.Lock() defer c.mu.Unlock() if entry, ok := c.entries[key]; ok { entry.Result = result log.Debug().Str("key", key).Int("items", len(result.Items)).Msg("cache entry updated") } else { log.Warn().Str("key", key).Msg("cache update for missing entry") } } func (c *IndexerCache) Remove(key string) { c.mu.Lock() defer c.mu.Unlock() delete(c.entries, key) log.Debug().Str("key", key).Msg("cache entry removed") }