@@ -26,11 +26,11 @@ func SetPanicHandler(handler PanicHandlerFunc) {
26
26
// Looper
27
27
type Looper struct {
28
28
running bool
29
+ jobs []* Job
29
30
startupTime time.Duration
30
- locker locker
31
31
hooks hooks
32
32
mu sync.RWMutex
33
- jobs [] * Job
33
+ locker locker
34
34
}
35
35
36
36
type (
@@ -46,18 +46,13 @@ type hooks struct {
46
46
}
47
47
48
48
type Config struct {
49
- // Locker for jobs
50
- //
51
- // Options:
52
- // PostgresLocker(ctx context.Context, db *sql.DB, table string)
53
- // RedisLocker(ctx context.Context, rc redis.UniversalClient)
54
- Locker locker
55
-
56
49
// Startup time ensuring a consistent delay between registered jobs on start of looper.
57
50
//
58
51
// StartupTime = 1 second; 5 registered jobs; Jobs would be initiated
59
52
// with 200ms delay
60
53
StartupTime time.Duration
54
+
55
+ Locker locker
61
56
}
62
57
63
58
type JobFn func (ctx context.Context ) error
@@ -226,7 +221,7 @@ func (l *Looper) StartJobByName(jobName string) error {
226
221
found = true
227
222
if j .Active && ! j .Started {
228
223
j .Started = true
229
- go j .start ()
224
+ go j .startLoop ()
230
225
}
231
226
}
232
227
@@ -263,7 +258,7 @@ func (l *Looper) startJobs() {
263
258
j .mu .Lock ()
264
259
if j .Active && ! j .Started {
265
260
j .Started = true
266
- go j .start ()
261
+ go j .startLoop ()
267
262
time .Sleep (delay )
268
263
}
269
264
@@ -299,18 +294,14 @@ func (l *Looper) Stop() {
299
294
l .mu .Unlock ()
300
295
}
301
296
302
- func (j * Job ) start () {
297
+ func (j * Job ) startLoop () {
303
298
defer func () {
304
299
j .mu .Lock ()
305
300
j .Started = false
306
301
j .contextCancel = nil
307
302
j .mu .Unlock ()
308
303
}()
309
304
310
- var errLock error
311
- var err error
312
- ctxLock := context .Background ()
313
-
314
305
for {
315
306
j .mu .RLock ()
316
307
if ! j .Active || ! j .Started {
@@ -319,65 +310,86 @@ func (j *Job) start() {
319
310
}
320
311
j .mu .RUnlock ()
321
312
322
- ctx , cancel := context .WithTimeout (context .Background (), j .Timeout )
323
-
324
- j .mu .Lock ()
325
- j .contextCancel = cancel
326
- j .Running = true
327
-
328
- var lo lock
329
-
330
- if j .WithLocker {
331
- lo , errLock = j .locker .lock (ctxLock , j .Name , j .Timeout )
332
- if errors .Is (errLock , ErrFailedToObtainLock ) {
333
- time .Sleep (time .Duration (time .Second ))
334
- j .Running = false
335
- cancel ()
336
- j .mu .Unlock ()
337
- continue
338
- }
313
+ start := time .Now ()
339
314
340
- if errLock != nil {
341
- err = errLock
342
- }
315
+ j .BeforeJob (j .Name )
316
+ err := j .start ()
317
+ if err != nil {
318
+ j .AfterJobError (j .Name , time .Since (start ), err )
319
+ time .Sleep (j .WaitAfterError )
320
+ } else {
321
+ j .AfterJob (j .Name , time .Since (start ))
322
+ time .Sleep (j .WaitAfterSuccess )
343
323
}
324
+ }
325
+ }
344
326
345
- j .BeforeJob (j .Name )
327
+ func (j * Job ) start () error {
328
+ defer func () {
329
+ j .mu .Lock ()
330
+ j .Running = false
346
331
j .mu .Unlock ()
332
+ }()
347
333
348
- start := time .Now ()
349
- if err == nil {
350
- err = j .Run (ctx )
351
- }
334
+ j .mu .Lock ()
335
+ j .Running = true
336
+ j .mu .Unlock ()
352
337
353
- if j .WithLocker && errLock == nil {
354
- errLock = lo .unlock (ctxLock )
338
+ lo , err := j .lock ()
339
+ if err != nil {
340
+ if errors .Is (err , ErrFailedToObtainLock ) {
341
+ time .Sleep (time .Second )
342
+ return nil
355
343
}
356
344
357
- if err != nil || errLock != nil {
358
- if err != nil {
359
- j .AfterJobError (j .Name , time .Since (start ), err )
360
- } else {
361
- j .AfterJobError (j .Name , time .Since (start ), errLock )
362
- }
345
+ return err
346
+ }
363
347
364
- time .Sleep (j .WaitAfterError )
365
- } else {
366
- j .AfterJob (j .Name , time .Since (start ))
367
- time .Sleep (j .WaitAfterSuccess )
348
+ ctx , cancel := context .WithTimeout (context .Background (), j .Timeout )
349
+ defer cancel ()
350
+
351
+ j .contextCancel = cancel
352
+
353
+ err = j .run (ctx )
354
+ if err != nil {
355
+ errLock := j .unlock (lo )
356
+ if errLock != nil {
357
+ return errors .Join (err , errLock )
368
358
}
369
359
370
- cancel ()
360
+ return err
361
+ }
362
+
363
+ err = j .unlock (lo )
364
+ if err != nil {
365
+ return err
371
366
}
367
+
368
+ return nil
369
+ }
370
+
371
+ func (j * Job ) lock () (lo lock , err error ) {
372
+ if j .WithLocker {
373
+ lo , err = j .locker .lock (context .Background (), j .Name , j .Timeout )
374
+ }
375
+
376
+ return lo , err
372
377
}
373
378
374
- func (j * Job ) Run (ctx context.Context ) (err error ) {
379
+ func (j * Job ) unlock (lo lock ) (err error ) {
380
+ if j .WithLocker {
381
+ return lo .unlock (context .Background ())
382
+ }
383
+
384
+ return nil
385
+ }
386
+
387
+ func (j * Job ) run (ctx context.Context ) (err error ) {
375
388
defer func () {
376
389
j .mu .Lock ()
377
390
defer j .mu .Unlock ()
378
391
379
392
j .LastRun = time .Now ()
380
- j .Running = false
381
393
382
394
r := recover ()
383
395
if r != nil {
0 commit comments