all repos — fixyoutube-go @ c5f478be5cffb0aeb698446718dc8a50e3914c30

A better way to embed YouTube videos everywhere (inspired by FixTweet).

volatile/volatile.go (view raw)

 1package volatile
 2
 3import (
 4	"fmt"
 5	"time"
 6
 7	"github.com/sirupsen/logrus"
 8)
 9
10var logger = logrus.New()
11
12type Element[V any] struct {
13	value     *V
14	Timestamp time.Time
15}
16
17type Volatile[K comparable, V any] struct {
18	data       map[K]Element[V]
19	timeToLive time.Duration
20}
21
22func (v *Volatile[K, V]) clean() int {
23	now := time.Now()
24	keysToDelete := []K{}
25
26	for key, value := range v.data {
27		if now.Sub(value.Timestamp) > v.timeToLive {
28			keysToDelete = append(keysToDelete, key)
29		}
30	}
31	for _, key := range keysToDelete {
32		delete(v.data, key)
33	}
34	return len(keysToDelete)
35}
36
37func (v *Volatile[K, V]) cleanupRoutine(interval time.Duration) {
38	ticker := time.NewTicker(interval)
39	defer ticker.Stop()
40
41	for {
42		select {
43		case <-ticker.C:
44			amt := v.clean()
45			logger.Debug(amt, " elements were automatically removed from cache.")
46		}
47	}
48}
49
50func NewVolatile[K comparable, V any](timeToLive time.Duration, cleanupInterval time.Duration) *Volatile[K, V] {
51	v := &Volatile[K, V]{
52		data:       make(map[K]Element[V]),
53		timeToLive: timeToLive,
54	}
55	go v.cleanupRoutine(cleanupInterval)
56	return v
57}
58
59func (v *Volatile[K, V]) Has(key K) bool {
60	v.clean()
61	_, ok := v.data[key]
62	return ok
63}
64
65func (v *Volatile[K, V]) Get(key K) (*V, error) {
66	v.clean()
67	element, ok := v.data[key]
68	if !ok {
69		return nil, fmt.Errorf("not found")
70	}
71	return element.value, nil
72}
73
74func (v *Volatile[K, V]) Remove(key K) (*V, error) {
75	v.clean()
76	value, ok := v.data[key]
77
78	if ok {
79		delete(v.data, key)
80		return value.value, nil
81	}
82
83	return nil, fmt.Errorf("not found")
84}
85
86func (v *Volatile[K, V]) Set(key K, value *V) error {
87	v.data[key] = Element[V]{value: value, Timestamp: time.Now()}
88	v.clean()
89	return nil
90}