@@ -27,8 +27,11 @@ type worker struct {
2727 idx uint32
2828 // Status of the worker.
2929 status WorkerStatus
30- // Pause channel between put to sleep and stop.
31- pause chan struct {}
30+ // Channel to control sleep and stop states.
31+ // This channel delivers two signals:
32+ // * wakeup for slept workers
33+ // * force close for active workers
34+ ctl chan struct {}
3235 // Last signal timestamp.
3336 lastTS int64
3437 // Worker instance.
@@ -42,7 +45,7 @@ func makeWorker(idx uint32, config *Config) *worker {
4245 w := & worker {
4346 idx : idx ,
4447 status : WorkerStatusIdle ,
45- pause : make (chan struct {}, 1 ),
48+ ctl : make (chan struct {}, 1 ),
4649 proc : config .Worker ,
4750 config : config ,
4851 }
@@ -70,7 +73,7 @@ func (w *worker) await(queue *Queue) {
7073 switch w .getStatus () {
7174 case WorkerStatusSleep :
7275 // Wait config.SleepInterval.
73- <- w .pause
76+ <- w .ctl
7477 case WorkerStatusActive :
7578 // Read itm from the stream.
7679 itm , ok := <- queue .stream
@@ -81,15 +84,30 @@ func (w *worker) await(queue *Queue) {
8184 }
8285 w .mw ().QueuePull ()
8386
87+ var intr bool
8488 // Check delayed execution.
8589 if itm .dexpire > 0 {
8690 now := queue .clk ().Now ().UnixNano ()
8791 if delta := time .Duration (itm .dexpire - now ); delta > 0 {
8892 // Processing time has not yet arrived. So wait till delay ends.
89- time .Sleep (delta )
93+ select {
94+ case <- time .After (delta ):
95+ break
96+ case <- w .ctl :
97+ // Waiting interrupted due to force close signal.
98+ intr = true
99+ // Calculate real wait time.
100+ delta = time .Duration (queue .clk ().Now ().UnixNano () - now )
101+ break
102+ }
90103 w .mw ().WorkerWait (w .idx , delta )
91104 }
92105 }
106+ if intr {
107+ // Return item back to the queue due to interrupt signal.
108+ _ = queue .renqueue (& itm )
109+ return
110+ }
93111
94112 // Forward itm to dequeuer.
95113 if err := w .proc .Do (itm .payload ); err != nil {
@@ -137,7 +155,7 @@ func (w *worker) wakeup() {
137155 }
138156 w .setStatus (WorkerStatusActive )
139157 w .mw ().WorkerWakeup (w .idx )
140- w .pause <- struct {}{}
158+ w .notifyCtl ()
141159}
142160
143161// Stop (or force stop) worker.
@@ -151,8 +169,19 @@ func (w *worker) stop(force bool) {
151169 }
152170 w .mw ().WorkerStop (w .idx , force , w .getStatus ())
153171 w .setStatus (WorkerStatusIdle )
154- // Notify pause channel about stop.
155- w .pause <- struct {}{}
172+ w .notifyCtl ()
173+ }
174+
175+ // Check if ctl channel is empty and send signal (wakeup or force close).
176+ func (w * worker ) notifyCtl () {
177+ // Check ctl channel for previously undelivered signal.
178+ if len (w .ctl ) > 0 {
179+ // Clear ctl channel to prevent locking.
180+ _ , _ = <- w .ctl
181+ }
182+
183+ // Send stop signal to ctl channel.
184+ w .ctl <- struct {}{}
156185}
157186
158187// Set worker status.
@@ -167,7 +196,7 @@ func (w *worker) getStatus() WorkerStatus {
167196
168197// Check if worker slept enough time.
169198func (w * worker ) sleptEnough () bool {
170- dur := time .Duration (time .Now ().UnixNano () - atomic .LoadInt64 (& w .lastTS ))
199+ dur := time .Duration (w . c (). Clock .Now ().UnixNano () - atomic .LoadInt64 (& w .lastTS ))
171200 return dur >= w .c ().SleepInterval
172201}
173202
0 commit comments