@@ -66,6 +66,11 @@ const (
66
66
67
67
var nowFn = time .Now
68
68
69
+ type work struct {
70
+ id int
71
+ fn WorkFunc
72
+ }
73
+
69
74
type WriterLease struct {
70
75
name string
71
76
backoff wait.Backoff
@@ -74,7 +79,8 @@ type WriterLease struct {
74
79
once chan struct {}
75
80
76
81
lock sync.Mutex
77
- queued map [string ]WorkFunc
82
+ id int
83
+ queued map [string ]* work
78
84
queue workqueue.DelayingInterface
79
85
state State
80
86
expires time.Time
@@ -95,7 +101,7 @@ func New(leaseDuration, retryInterval time.Duration) *WriterLease {
95
101
maxBackoff : leaseDuration ,
96
102
retryInterval : retryInterval ,
97
103
98
- queued : make (map [string ]WorkFunc ),
104
+ queued : make (map [string ]* work ),
99
105
queue : workqueue .NewDelayingQueue (),
100
106
once : make (chan struct {}),
101
107
}
@@ -110,7 +116,7 @@ func NewWithBackoff(name string, leaseDuration, retryInterval time.Duration, bac
110
116
maxBackoff : leaseDuration ,
111
117
retryInterval : retryInterval ,
112
118
113
- queued : make (map [string ]WorkFunc ),
119
+ queued : make (map [string ]* work ),
114
120
queue : workqueue .NewNamedDelayingQueue (name ),
115
121
once : make (chan struct {}),
116
122
}
@@ -155,7 +161,8 @@ func (l *WriterLease) WaitUntil(t time.Duration) (bool, bool) {
155
161
func (l * WriterLease ) Try (key string , fn WorkFunc ) {
156
162
l .lock .Lock ()
157
163
defer l .lock .Unlock ()
158
- l .queued [key ] = fn
164
+ l .id ++
165
+ l .queued [key ] = & work {fn : fn , id : l .id }
159
166
if l .state == Follower {
160
167
delay := l .expires .Sub (nowFn ())
161
168
// no matter what, always wait at least some amount of time as a follower to give the nominal
@@ -196,7 +203,7 @@ func (l *WriterLease) Remove(key string) {
196
203
delete (l .queued , key )
197
204
}
198
205
199
- func (l * WriterLease ) get (key string ) WorkFunc {
206
+ func (l * WriterLease ) get (key string ) * work {
200
207
l .lock .Lock ()
201
208
defer l .lock .Unlock ()
202
209
return l .queued [key ]
@@ -215,8 +222,8 @@ func (l *WriterLease) work() bool {
215
222
}
216
223
key := item .(string )
217
224
218
- fn := l .get (key )
219
- if fn == nil {
225
+ work := l .get (key )
226
+ if work == nil {
220
227
glog .V (4 ).Infof ("[%s] Work item %s was cleared, done" , l .name , key )
221
228
l .queue .Done (key )
222
229
return true
@@ -236,7 +243,7 @@ func (l *WriterLease) work() bool {
236
243
glog .V (4 ).Infof ("[%s] Lease owner or electing, running %s" , l .name , key )
237
244
}
238
245
239
- isLeader , retry := fn ()
246
+ isLeader , retry := work . fn ()
240
247
if retry {
241
248
// come back in a bit
242
249
glog .V (4 ).Infof ("[%s] Retrying %s" , l .name , key )
@@ -245,11 +252,11 @@ func (l *WriterLease) work() bool {
245
252
return true
246
253
}
247
254
248
- l .finishKey (key , isLeader )
255
+ l .finishKey (key , isLeader , work . id )
249
256
return true
250
257
}
251
258
252
- func (l * WriterLease ) finishKey (key string , isLeader bool ) {
259
+ func (l * WriterLease ) finishKey (key string , isLeader bool , id int ) {
253
260
l .lock .Lock ()
254
261
defer l .lock .Unlock ()
255
262
@@ -271,7 +278,9 @@ func (l *WriterLease) finishKey(key string, isLeader bool) {
271
278
}
272
279
l .expires = nowFn ().Add (l .nextBackoff ())
273
280
}
274
- delete (l .queued , key )
281
+ if l .queued [key ].id == id {
282
+ delete (l .queued , key )
283
+ }
275
284
// close the channel before we remove the key from the queue to prevent races in Wait
276
285
if resolvedElection {
277
286
close (l .once )
0 commit comments