// Copyright (c) 2021-2025, Ludvig Lundgren and the autobrr contributors. // SPDX-License-Identifier: GPL-2.0-or-later package ttlcache import ( "time" "github.com/autobrr/autobrr/pkg/timecache" ) func New[K comparable, V any](options Options[K, V]) *Cache[K, V] { c := Cache[K, V]{ o: options, ch: make(chan time.Time, 1000), m: make(map[K]Item[V]), } if options.defaultTTL != NoTTL && options.defaultResolution == 0 { c.tc = *timecache.New(timecache.Options{}.Round(options.defaultTTL / 2)) } else if options.defaultResolution != 0 { c.tc = *timecache.New(timecache.Options{}.Round(options.defaultResolution)) } go c.startExpirations() return &c } func (c *Cache[K, V]) Get(key K) (V, bool) { it, ok := c.GetItem(key) if !ok { return *new(V), ok } return it.GetValue(), ok } func (c *Cache[K, V]) GetItem(key K) (Item[V], bool) { it, ok := c.get(key) if !ok { return it, ok } if !c.o.noUpdateTime && !it.t.IsZero() { if _, t := c.getDuration(it.d); t.After(it.t) { c.set(key, it) } } return it, ok } func (c *Cache[K, V]) GetOrSet(key K, value V, duration time.Duration) (V, bool) { it, ok := c.GetOrSetItem(key, value, duration) if !ok { return *new(V), ok } return it.GetValue(), ok } func (c *Cache[K, V]) fixupDuration(duration time.Duration) time.Duration { if c.o.defaultTTL == NoTTL && duration == DefaultTTL { return NoTTL } return duration } func (c *Cache[K, V]) GetOrSetItem(key K, value V, duration time.Duration) (Item[V], bool) { it, ok := c.getOrSet(key, Item[V]{v: value, d: c.fixupDuration(duration)}) if !ok { return Item[V]{}, ok } return it, ok } func (c *Cache[K, V]) Set(key K, value V, duration time.Duration) bool { c.SetItem(key, value, duration) return true } func (c *Cache[K, V]) SetItem(key K, value V, duration time.Duration) Item[V] { return c.set(key, Item[V]{v: value, d: c.fixupDuration(duration)}) } func (c *Cache[K, V]) Delete(key K) { c.delete(key, ReasonDeleted) } func (c *Cache[K, V]) GetKeys() []K { return c.getkeys() } func (c *Cache[K, V]) Close() { c.close() } func (i *Item[V]) GetDuration() time.Duration { return i.getDuration() } func (i *Item[V]) GetTime() time.Time { return i.getTime() } func (i *Item[V]) GetValue() V { return i.getValue() } func (o Options[K, V]) SetTimerResolution(d time.Duration) Options[K, V] { o.defaultResolution = d return o } func (o Options[K, V]) SetDefaultTTL(d time.Duration) Options[K, V] { o.defaultTTL = d return o } func (o Options[K, V]) SetDeallocationFunc(f DeallocationFunc[K, V]) Options[K, V] { o.deallocationFunc = f return o } func (o Options[K, V]) DisableUpdateTime(val bool) Options[K, V] { o.noUpdateTime = val return o }