package domain import ( "context" "sync" "time" "gitea.nik4nao.com/nik/home-services/ai-gateway/internal/core/ports/driven" ) // LightCache keeps recently-fetched light discovery data in memory. type LightCache struct { ttl time.Duration loadFunc func(context.Context) ([]driven.Light, error) mu sync.RWMutex lights []driven.Light loadedAt time.Time } // NewLightCache constructs a TTL-based in-memory light cache. func NewLightCache(ttl time.Duration, loadFunc func(context.Context) ([]driven.Light, error)) *LightCache { return &LightCache{ttl: ttl, loadFunc: loadFunc} } // Get returns the cached lights, refreshing lazily when empty or stale. func (c *LightCache) Get(ctx context.Context) ([]driven.Light, error) { c.mu.RLock() if len(c.lights) > 0 && time.Since(c.loadedAt) < c.ttl { lights := append([]driven.Light(nil), c.lights...) c.mu.RUnlock() return lights, nil } c.mu.RUnlock() c.mu.Lock() defer c.mu.Unlock() if len(c.lights) > 0 && time.Since(c.loadedAt) < c.ttl { return append([]driven.Light(nil), c.lights...), nil } lights, err := c.loadFunc(ctx) if err != nil { return nil, err } c.lights = append([]driven.Light(nil), lights...) c.loadedAt = time.Now() return append([]driven.Light(nil), c.lights...), nil }