all repos

mugit @ e1c61c6

🐮 git server that your cow will love

mugit/internal/cache/in_memory.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
cache: refactor; tests, 3 months ago
1
package cache
2
3
import (
4
	"sync"
5
	"time"
6
)
7
8
type item[T any] struct {
9
	v      T
10
	expiry time.Time
11
}
12
13
func (i item[T]) isExpired() bool {
14
	return time.Now().After(i.expiry)
15
}
16
17
type InMemory[T any] struct {
18
	mu   sync.RWMutex
19
	ttl  time.Duration
20
	data map[string]item[T]
21
}
22
23
func NewInMemory[T any](ttl time.Duration) *InMemory[T] {
24
	c := &InMemory[T]{
25
		data: make(map[string]item[T]),
26
		ttl:  ttl,
27
	}
28
29
	go c.clean()
30
	return c
31
}
32
33
func (m *InMemory[T]) Set(key string, val T) {
34
	m.mu.Lock()
35
	defer m.mu.Unlock()
36
	m.data[key] = item[T]{
37
		v:      val,
38
		expiry: time.Now().Add(m.ttl),
39
	}
40
}
41
42
func (m *InMemory[T]) Get(key string) (T, bool) {
43
	m.mu.Lock()
44
	defer m.mu.Unlock()
45
46
	val, found := m.data[key]
47
	if !found || val.isExpired() {
48
		var t T
49
		return t, false
50
	}
51
	return val.v, true
52
}
53
54
func (m *InMemory[T]) clean() {
55
	for range time.Tick(5 * time.Second) {
56
		m.mu.Lock()
57
		for k, v := range m.data {
58
			if v.isExpired() {
59
				delete(m.data, k)
60
			}
61
		}
62
		m.mu.Unlock()
63
	}
64
}