forked from Mrs4s/MiraiGo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathttl.go
103 lines (88 loc) · 2.12 KB
/
ttl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package utils
import (
"sync"
"time"
)
// https://github.com/Konstantin8105/SimpleTTL
// entry - typical element of cache
type entry[T any] struct {
expiry time.Time
value T
}
// Cache - simple implementation of cache
// More information: https://en.wikipedia.org/wiki/Time_to_live
type Cache[T any] struct {
lock sync.RWMutex
cache map[string]*entry[T]
}
// NewCache - initialization of new cache.
// For avoid mistake - minimal time to live is 1 minute.
// For simplification, - key is string and cache haven`t stop method
func NewCache[T any](interval time.Duration) *Cache[T] {
if interval < time.Second {
interval = time.Second
}
cache := &Cache[T]{cache: make(map[string]*entry[T])}
go func() {
ticker := time.NewTicker(interval)
for {
// wait of ticker
now := <-ticker.C
// remove entry outside TTL
cache.lock.Lock()
for id, entry := range cache.cache {
if entry == nil || entry.expiry.Before(now) {
delete(cache.cache, id)
}
}
cache.lock.Unlock()
}
}()
return cache
}
// Count - return amount element of TTL map.
func (cache *Cache[_]) Count() int {
cache.lock.RLock()
defer cache.lock.RUnlock()
return len(cache.cache)
}
// Get - return value from cache
func (cache *Cache[T]) Get(key string) (value T, _ bool) {
cache.lock.RLock()
defer cache.lock.RUnlock()
e, ok := cache.cache[key]
if ok && e.expiry.After(time.Now()) {
return e.value, true
}
return
}
func (cache *Cache[T]) GetAndUpdate(key string, ttl time.Duration) (_ T, _ bool) {
cache.lock.RLock()
defer cache.lock.RUnlock()
if e, ok := cache.cache[key]; ok {
e.expiry = time.Now().Add(ttl)
return e.value, true
}
return
}
// Add - add key/value in cache
func (cache *Cache[T]) Add(key string, value T, ttl time.Duration) {
cache.lock.Lock()
defer cache.lock.Unlock()
cache.cache[key] = &entry[T]{
value: value,
expiry: time.Now().Add(ttl),
}
}
// GetKeys - return all keys of cache map
func (cache *Cache[_]) GetKeys() []string {
cache.lock.RLock()
defer cache.lock.RUnlock()
keys := make([]string, len(cache.cache))
var i int
for k := range cache.cache {
keys[i] = k
i++
}
return keys
}