8
8
"sync/atomic"
9
9
"time"
10
10
11
- "github.com/golang-queue/queue"
12
-
13
11
"github.com/go-redis/redis/v8"
12
+ "github.com/golang-queue/queue"
14
13
)
15
14
16
15
var _ queue.Worker = (* Worker )(nil )
@@ -30,11 +29,12 @@ type Worker struct {
30
29
channel string
31
30
channelSize int
32
31
33
- stopOnce sync.Once
34
- stop chan struct {}
35
- runFunc func (context.Context , queue.QueuedMessage ) error
36
- logger queue.Logger
37
- stopFlag int32
32
+ stopOnce sync.Once
33
+ stop chan struct {}
34
+ runFunc func (context.Context , queue.QueuedMessage ) error
35
+ logger queue.Logger
36
+ stopFlag int32
37
+ busyWorkers uint64
38
38
}
39
39
40
40
// WithAddr setup the addr of redis
@@ -143,23 +143,39 @@ func NewWorker(opts ...Option) *Worker {
143
143
return w
144
144
}
145
145
146
+ func (w * Worker ) incBusyWorker () {
147
+ atomic .AddUint64 (& w .busyWorkers , 1 )
148
+ }
149
+
150
+ func (w * Worker ) decBusyWorker () {
151
+ atomic .AddUint64 (& w .busyWorkers , ^ uint64 (0 ))
152
+ }
153
+
154
+ func (w * Worker ) BusyWorkers () uint64 {
155
+ return atomic .LoadUint64 (& w .busyWorkers )
156
+ }
157
+
146
158
// BeforeRun run script before start worker
147
- func (s * Worker ) BeforeRun () error {
159
+ func (w * Worker ) BeforeRun () error {
148
160
return nil
149
161
}
150
162
151
163
// AfterRun run script after start worker
152
- func (s * Worker ) AfterRun () error {
164
+ func (w * Worker ) AfterRun () error {
153
165
return nil
154
166
}
155
167
156
- func (s * Worker ) handle (job queue.Job ) error {
168
+ func (w * Worker ) handle (job queue.Job ) error {
157
169
// create channel with buffer size 1 to avoid goroutine leak
158
170
done := make (chan error , 1 )
159
171
panicChan := make (chan interface {}, 1 )
160
172
startTime := time .Now ()
161
173
ctx , cancel := context .WithTimeout (context .Background (), job .Timeout )
162
- defer cancel ()
174
+ w .incBusyWorker ()
175
+ defer func () {
176
+ cancel ()
177
+ w .decBusyWorker ()
178
+ }()
163
179
164
180
// run the job
165
181
go func () {
@@ -171,15 +187,15 @@ func (s *Worker) handle(job queue.Job) error {
171
187
}()
172
188
173
189
// run custom process function
174
- done <- s .runFunc (ctx , job )
190
+ done <- w .runFunc (ctx , job )
175
191
}()
176
192
177
193
select {
178
194
case p := <- panicChan :
179
195
panic (p )
180
196
case <- ctx .Done (): // timeout reached
181
197
return ctx .Err ()
182
- case <- s .stop : // shutdown service
198
+ case <- w .stop : // shutdown service
183
199
// cancel job
184
200
cancel ()
185
201
@@ -199,39 +215,39 @@ func (s *Worker) handle(job queue.Job) error {
199
215
}
200
216
201
217
// Shutdown worker
202
- func (s * Worker ) Shutdown () error {
203
- if ! atomic .CompareAndSwapInt32 (& s .stopFlag , 0 , 1 ) {
218
+ func (w * Worker ) Shutdown () error {
219
+ if ! atomic .CompareAndSwapInt32 (& w .stopFlag , 0 , 1 ) {
204
220
return queue .ErrQueueShutdown
205
221
}
206
222
207
- s .stopOnce .Do (func () {
208
- s .pubsub .Close ()
209
- s .rdb .Close ()
210
- close (s .stop )
223
+ w .stopOnce .Do (func () {
224
+ w .pubsub .Close ()
225
+ w .rdb .Close ()
226
+ close (w .stop )
211
227
})
212
228
return nil
213
229
}
214
230
215
231
// Capacity for channel
216
- func (s * Worker ) Capacity () int {
232
+ func (w * Worker ) Capacity () int {
217
233
return 0
218
234
}
219
235
220
236
// Usage for count of channel usage
221
- func (s * Worker ) Usage () int {
237
+ func (w * Worker ) Usage () int {
222
238
return 0
223
239
}
224
240
225
241
// Queue send notification to queue
226
- func (s * Worker ) Queue (job queue.QueuedMessage ) error {
227
- if atomic .LoadInt32 (& s .stopFlag ) == 1 {
242
+ func (w * Worker ) Queue (job queue.QueuedMessage ) error {
243
+ if atomic .LoadInt32 (& w .stopFlag ) == 1 {
228
244
return queue .ErrQueueShutdown
229
245
}
230
246
231
247
ctx := context .Background ()
232
248
233
249
// Publish a message.
234
- err := s .rdb .Publish (ctx , s .channel , job .Bytes ()).Err ()
250
+ err := w .rdb .Publish (ctx , w .channel , job .Bytes ()).Err ()
235
251
if err != nil {
236
252
return err
237
253
}
@@ -240,57 +256,57 @@ func (s *Worker) Queue(job queue.QueuedMessage) error {
240
256
}
241
257
242
258
// Run start the worker
243
- func (s * Worker ) Run () error {
259
+ func (w * Worker ) Run () error {
244
260
// check queue status
245
261
select {
246
- case <- s .stop :
262
+ case <- w .stop :
247
263
return nil
248
264
default :
249
265
}
250
266
251
267
var options []redis.ChannelOption
252
268
ctx := context .Background ()
253
269
254
- if s .channelSize > 1 {
255
- options = append (options , redis .WithChannelSize (s .channelSize ))
270
+ if w .channelSize > 1 {
271
+ options = append (options , redis .WithChannelSize (w .channelSize ))
256
272
}
257
273
258
- ch := s .pubsub .Channel (options ... )
274
+ ch := w .pubsub .Channel (options ... )
259
275
// make sure the connection is successful
260
- err := s .pubsub .Ping (ctx )
276
+ err := w .pubsub .Ping (ctx )
261
277
if err != nil {
262
278
return err
263
279
}
264
280
265
281
for {
266
282
// check queue status
267
283
select {
268
- case <- s .stop :
284
+ case <- w .stop :
269
285
return nil
270
286
default :
271
287
}
272
288
273
289
select {
274
290
case m , ok := <- ch :
275
291
select {
276
- case <- s .stop :
292
+ case <- w .stop :
277
293
return nil
278
294
default :
279
295
}
280
296
281
297
if ! ok {
282
- return fmt .Errorf ("redis pubsub: channel=%s closed" , s .channel )
298
+ return fmt .Errorf ("redis pubsub: channel=%s closed" , w .channel )
283
299
}
284
300
285
301
var data queue.Job
286
302
if err := json .Unmarshal ([]byte (m .Payload ), & data ); err != nil {
287
- s .logger .Error ("json unmarshal error: " , err )
303
+ w .logger .Error ("json unmarshal error: " , err )
288
304
continue
289
305
}
290
- if err := s .handle (data ); err != nil {
291
- s .logger .Error ("handle job error: " , err )
306
+ if err := w .handle (data ); err != nil {
307
+ w .logger .Error ("handle job error: " , err )
292
308
}
293
- case <- s .stop :
309
+ case <- w .stop :
294
310
return nil
295
311
}
296
312
}
0 commit comments