-
Notifications
You must be signed in to change notification settings - Fork 0
/
cleaner.go
151 lines (114 loc) · 3.56 KB
/
cleaner.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package krot
import (
"context"
"fmt"
"time"
)
// KeyCleanerHook defines the signature for key cleaner hooks.
type KeyCleanerHook func(cleaner KeyCleaner)
// KeyCleanerHooks defines a collection of key cleaner hooks.
type KeyCleanerHooks []KeyCleanerHook
// Run executes the key cleaner hooks.
func (h KeyCleanerHooks) Run(cleaner KeyCleaner) {
for _, hook := range h {
hook(cleaner)
}
}
// KeyCleanerState defines the state of the key cleaner.
type KeyCleanerState uint
const (
// KeyCleanerStateIdle represents the idle state of the cleaner.
KeyCleanerStateIdle KeyCleanerState = iota
// KeyCleanerStateCleaning represents the cleaning state of the cleaner.
KeyCleanerStateCleaning
)
// KeyCleanerStatus defines the status of the key cleaner.
type KeyCleanerStatus uint
const (
// KeyCleanerStatusStopped represents the stopped status of the cleaner.
KeyCleanerStatusStopped KeyCleanerStatus = iota
// KeyCleanerStatusStarted represents the started status of the cleaner.
KeyCleanerStatusStarted
)
type KeyCleaner interface {
// State returns the current state of the cleaner.
State() KeyCleanerState
// Status returns the current status of the cleaner.
Status() KeyCleanerStatus
// OnStart registers hooks to be executed when the cleaner starts.
OnStart(hooks ...KeyCleanerHook)
// OnStop registers hooks to be executed when the cleaner stops.
OnStop(hooks ...KeyCleanerHook)
// BeforeCleaning registers hooks to be executed before the cleaner starts cleaning.
BeforeCleaning(hooks ...KeyCleanerHook)
// AfterCleaning registers hooks to be executed after the cleaner finishes cleaning.
AfterCleaning(hooks ...KeyCleanerHook)
// Start begins the key cleaning process. It requires a context for managing
Start(ctx context.Context, interval time.Duration) error
// Stop halts the key cleaning process.
Stop()
}
type keyCleaner struct {
status KeyCleanerStatus
state KeyCleanerState
onStartHooks KeyCleanerHooks
onStopHooks KeyCleanerHooks
beforeCleaningHooks KeyCleanerHooks
afterCleaningHooks KeyCleanerHooks
ctx context.Context
cancel context.CancelFunc
storage KeyStorage
}
func NewKeyCleaner(storage KeyStorage) KeyCleaner {
return &keyCleaner{storage: storage}
}
func (c *keyCleaner) State() KeyCleanerState {
return c.state
}
func (c *keyCleaner) Status() KeyCleanerStatus {
return c.status
}
func (c *keyCleaner) OnStart(hooks ...KeyCleanerHook) {
c.onStartHooks = append(c.onStartHooks, hooks...)
}
func (c *keyCleaner) OnStop(hooks ...KeyCleanerHook) {
c.onStopHooks = append(c.onStopHooks, hooks...)
}
func (c *keyCleaner) BeforeCleaning(hooks ...KeyCleanerHook) {
c.beforeCleaningHooks = append(c.beforeCleaningHooks, hooks...)
}
func (c *keyCleaner) AfterCleaning(hooks ...KeyCleanerHook) {
c.afterCleaningHooks = append(c.afterCleaningHooks, hooks...)
}
func (c *keyCleaner) Start(ctx context.Context, interval time.Duration) error {
if c.status == KeyCleanerStatusStarted {
return fmt.Errorf("cleaner is already running")
}
c.ctx, c.cancel = context.WithCancel(ctx)
c.status = KeyCleanerStatusStarted
go c.run(ctx, interval)
c.onStartHooks.Run(c)
return nil
}
func (c *keyCleaner) Stop() {
if c.cancel != nil {
c.status = KeyCleanerStatusStopped
c.cancel()
c.onStopHooks.Run(c)
}
}
func (c *keyCleaner) run(context context.Context, interval time.Duration) {
for {
select {
case <-c.ctx.Done():
return
default:
c.state = KeyCleanerStateIdle
time.Sleep(interval)
c.beforeCleaningHooks.Run(c)
c.state = KeyCleanerStateCleaning
c.storage.ClearDeprecated(context)
c.afterCleaningHooks.Run(c)
}
}
}