/
cache.go
109 lines (86 loc) · 1.77 KB
/
cache.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
104
105
106
107
108
109
package secretsmanager
import (
"context"
"sync"
"time"
)
type BlackList map[string]struct{}
type secret struct {
value string
createdAt time.Time
}
func (s secret) IsZero() bool {
return s.value == "" && s.createdAt.IsZero()
}
var (
zeroSecret = secret{}
)
type Janitor struct {
current, previous, pending secret
cacheMu sync.RWMutex
bl BlackList
interval time.Duration
done chan struct{}
once sync.Once
}
func NewJanitor(interval time.Duration) *Janitor {
return &Janitor{
interval: interval,
done: make(chan struct{}),
bl: make(BlackList),
}
}
func (j *Janitor) Run(ctx context.Context, onCleanup func()) {
cleanup := func() {
j.setCache(zeroSecret, zeroSecret, zeroSecret)
j.clearBlackList()
if onCleanup != nil {
onCleanup()
}
}
go func() {
ticker := time.NewTicker(j.interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
cleanup()
case <-j.done:
cleanup()
return
case <-ctx.Done():
j.stop()
}
}
}()
}
func (j *Janitor) getCache() (cur, prev, pen secret, found bool) {
j.cacheMu.Lock()
defer j.cacheMu.Unlock()
cur, prev, pen, found = j.current, j.previous, j.pending, !j.current.IsZero()
return
}
func (j *Janitor) setCache(cur, prev, pen secret) {
j.cacheMu.Lock()
defer j.cacheMu.Unlock()
j.current, j.previous, j.pending = cur, prev, pen
}
func (j *Janitor) blackList(val string) {
j.cacheMu.Lock()
defer j.cacheMu.Unlock()
j.bl[val] = struct{}{}
}
func (j *Janitor) isBlackListed(val string) bool {
j.cacheMu.Lock()
defer j.cacheMu.Unlock()
_, ok := j.bl[val]
return ok
}
func (j *Janitor) clearBlackList() {
j.cacheMu.Lock()
defer j.cacheMu.Unlock()
j.bl = make(BlackList)
}
func (j *Janitor) stop() {
j.once.Do(func() { close(j.done) })
}