autobrr/pkg/ttlcache/ttlcache.go

130 lines
2.8 KiB
Go

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