4
4
"context"
5
5
"sync"
6
6
"sync/atomic"
7
+ "time"
7
8
8
9
"github.com/golang-queue/queue"
9
10
@@ -23,11 +24,11 @@ type Worker struct {
23
24
db int
24
25
connectionString string
25
26
password string
27
+ channel string
28
+ channelSize int
26
29
27
- startOnce sync.Once
28
30
stopOnce sync.Once
29
31
stop chan struct {}
30
- channel string
31
32
runFunc func (context.Context , queue.QueuedMessage ) error
32
33
logger queue.Logger
33
34
stopFlag int32
@@ -48,6 +49,13 @@ func WithDB(db int) Option {
48
49
}
49
50
}
50
51
52
+ // WithChannelSize redis password
53
+ func WithChannelSize (size int ) Option {
54
+ return func (w * Worker ) {
55
+ w .channelSize = size
56
+ }
57
+ }
58
+
51
59
// WithPassword redis password
52
60
func WithPassword (passwd string ) Option {
53
61
return func (w * Worker ) {
@@ -140,7 +148,48 @@ func (s *Worker) AfterRun() error {
140
148
}
141
149
142
150
func (s * Worker ) handle (job queue.Job ) error {
143
- return nil
151
+ // create channel with buffer size 1 to avoid goroutine leak
152
+ done := make (chan error , 1 )
153
+ panicChan := make (chan interface {}, 1 )
154
+ startTime := time .Now ()
155
+ ctx , cancel := context .WithTimeout (context .Background (), job .Timeout )
156
+ defer cancel ()
157
+
158
+ // run the job
159
+ go func () {
160
+ // handle panic issue
161
+ defer func () {
162
+ if p := recover (); p != nil {
163
+ panicChan <- p
164
+ }
165
+ }()
166
+
167
+ // run custom process function
168
+ done <- s .runFunc (ctx , job )
169
+ }()
170
+
171
+ select {
172
+ case p := <- panicChan :
173
+ panic (p )
174
+ case <- ctx .Done (): // timeout reached
175
+ return ctx .Err ()
176
+ case <- s .stop : // shutdown service
177
+ // cancel job
178
+ cancel ()
179
+
180
+ leftTime := job .Timeout - time .Since (startTime )
181
+ // wait job
182
+ select {
183
+ case <- time .After (leftTime ):
184
+ return context .DeadlineExceeded
185
+ case err := <- done : // job finish
186
+ return err
187
+ case p := <- panicChan :
188
+ panic (p )
189
+ }
190
+ case err := <- done : // job finish
191
+ return err
192
+ }
144
193
}
145
194
146
195
// Shutdown worker
@@ -150,10 +199,7 @@ func (s *Worker) Shutdown() error {
150
199
}
151
200
152
201
s .stopOnce .Do (func () {
153
- if atomic .LoadInt32 (& s .startFlag ) == 1 {
154
- s .rdb .Close ()
155
- }
156
-
202
+ s .rdb .Close ()
157
203
close (s .stop )
158
204
})
159
205
return nil
@@ -180,5 +226,12 @@ func (s *Worker) Queue(job queue.QueuedMessage) error {
180
226
181
227
// Run start the worker
182
228
func (s * Worker ) Run () error {
229
+ // check queue status
230
+ select {
231
+ case <- s .stop :
232
+ return queue .ErrQueueShutdown
233
+ default :
234
+ }
235
+
183
236
return nil
184
237
}
0 commit comments