@@ -7,12 +7,19 @@ import (
7
7
"k8s.io/client-go/util/flowcontrol"
8
8
)
9
9
10
- // Scheduler is a self-balancing, rate-limited, bucketed queue that can periodically invoke
10
+ // NOTE: scheduler's semantics do not lend it for reuse elsewhere and its use in
11
+ // this package quite probably has some odd corner cases/race conditions. If
12
+ // these cause problems in the future, this implementation should be replaced
13
+ // with a new and simpler one based on container/heap. End users looking for a
14
+ // component like this: see if k8s.io/client-go/util/workqueue.NewDelayingQueue
15
+ // suits your needs.
16
+
17
+ // scheduler is a self-balancing, rate-limited, bucketed queue that can periodically invoke
11
18
// an action on all items in a bucket before moving to the next bucket. A ratelimiter sets
12
19
// an upper bound on the number of buckets processed per unit time. The queue has a key and a
13
20
// value, so both uniqueness and equality can be tested (key must be unique, value can carry
14
21
// info for the next processing). Items remain in the queue until removed by a call to Remove().
15
- type Scheduler struct {
22
+ type scheduler struct {
16
23
handle func (key , value interface {})
17
24
position int
18
25
limiter flowcontrol.RateLimiter
@@ -23,32 +30,32 @@ type Scheduler struct {
23
30
24
31
type bucket map [interface {}]interface {}
25
32
26
- // NewScheduler creates a scheduler with bucketCount buckets, a rate limiter for restricting
33
+ // newScheduler creates a scheduler with bucketCount buckets, a rate limiter for restricting
27
34
// the rate at which buckets are processed, and a function to invoke when items are scanned in
28
35
// a bucket.
29
36
// TODO: remove DEBUG statements from this file once this logic has been adequately validated.
30
- func NewScheduler (bucketCount int , bucketLimiter flowcontrol.RateLimiter , fn func (key , value interface {})) * Scheduler {
37
+ func newScheduler (bucketCount int , bucketLimiter flowcontrol.RateLimiter , fn func (key , value interface {})) * scheduler {
31
38
// Add one more bucket to serve as the "current" bucket
32
39
bucketCount ++
33
40
buckets := make ([]bucket , bucketCount )
34
41
for i := range buckets {
35
42
buckets [i ] = make (bucket )
36
43
}
37
- return & Scheduler {
44
+ return & scheduler {
38
45
handle : fn ,
39
46
buckets : buckets ,
40
47
limiter : bucketLimiter ,
41
48
}
42
49
}
43
50
44
51
// RunUntil launches the scheduler until ch is closed.
45
- func (s * Scheduler ) RunUntil (ch <- chan struct {}) {
52
+ func (s * scheduler ) RunUntil (ch <- chan struct {}) {
46
53
go utilwait .Until (s .RunOnce , 0 , ch )
47
54
}
48
55
49
56
// RunOnce takes a single item out of the current bucket and processes it. If
50
57
// the bucket is empty, we wait for the rate limiter before returning.
51
- func (s * Scheduler ) RunOnce () {
58
+ func (s * scheduler ) RunOnce () {
52
59
key , value , last := s .next ()
53
60
if last {
54
61
s .limiter .Accept ()
@@ -58,13 +65,13 @@ func (s *Scheduler) RunOnce() {
58
65
}
59
66
60
67
// at returns the bucket index relative to the current bucket.
61
- func (s * Scheduler ) at (inc int ) int {
68
+ func (s * scheduler ) at (inc int ) int {
62
69
return (s .position + inc + len (s .buckets )) % len (s .buckets )
63
70
}
64
71
65
72
// next takes a key from the current bucket and places it in the last bucket, returns the
66
73
// removed key. Returns true if the current bucket is empty and no key and value were returned.
67
- func (s * Scheduler ) next () (interface {}, interface {}, bool ) {
74
+ func (s * scheduler ) next () (interface {}, interface {}, bool ) {
68
75
s .mu .Lock ()
69
76
defer s .mu .Unlock ()
70
77
@@ -85,7 +92,7 @@ func (s *Scheduler) next() (interface{}, interface{}, bool) {
85
92
// removes the previous key and value and will place the item in a new bucket. This allows callers to ensure
86
93
// that Add'ing a new item to the queue purges old versions of the item, while Remove can be conditional on
87
94
// removing only the known old version.
88
- func (s * Scheduler ) Add (key , value interface {}) {
95
+ func (s * scheduler ) Add (key , value interface {}) {
89
96
s .mu .Lock ()
90
97
defer s .mu .Unlock ()
91
98
@@ -114,7 +121,7 @@ func (s *Scheduler) Add(key, value interface{}) {
114
121
115
122
// Remove takes the key out of all buckets. If value is non-nil, the key will only be removed if it has
116
123
// the same value. Returns true if the key was removed.
117
- func (s * Scheduler ) Remove (key , value interface {}) bool {
124
+ func (s * scheduler ) Remove (key , value interface {}) bool {
118
125
s .mu .Lock ()
119
126
defer s .mu .Unlock ()
120
127
@@ -132,7 +139,7 @@ func (s *Scheduler) Remove(key, value interface{}) bool {
132
139
}
133
140
134
141
// Delay moves the key to the end of the chain if it exists.
135
- func (s * Scheduler ) Delay (key interface {}) {
142
+ func (s * scheduler ) Delay (key interface {}) {
136
143
s .mu .Lock ()
137
144
defer s .mu .Unlock ()
138
145
@@ -149,7 +156,7 @@ func (s *Scheduler) Delay(key interface{}) {
149
156
}
150
157
151
158
// Len returns the number of scheduled items.
152
- func (s * Scheduler ) Len () int {
159
+ func (s * scheduler ) Len () int {
153
160
s .mu .Lock ()
154
161
defer s .mu .Unlock ()
155
162
@@ -162,7 +169,7 @@ func (s *Scheduler) Len() int {
162
169
163
170
// Map returns a copy of the scheduler contents, but does not copy the keys or values themselves.
164
171
// If values and keys are not immutable, changing the value will affect the value in the queue.
165
- func (s * Scheduler ) Map () map [interface {}]interface {} {
172
+ func (s * scheduler ) Map () map [interface {}]interface {} {
166
173
s .mu .Lock ()
167
174
defer s .mu .Unlock ()
168
175
0 commit comments