Skip to content

Commit 399ac28

Browse files
Add AfterJobRunsWithPanic (#733)
1 parent 5f94f39 commit 399ac28

File tree

5 files changed

+70
-9
lines changed

5 files changed

+70
-9
lines changed

errors.go

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var (
3333
ErrWeeklyJobDaysOfTheWeekNil = fmt.Errorf("gocron: WeeklyJob: daysOfTheWeek must not be nil")
3434
ErrWeeklyJobHours = fmt.Errorf("gocron: WeeklyJob: atTimes hours must be between 0 and 23 inclusive")
3535
ErrWeeklyJobMinutesSeconds = fmt.Errorf("gocron: WeeklyJob: atTimes minutes and seconds must be between 0 and 59 inclusive")
36+
ErrPanicRecovered = fmt.Errorf("gocron: panic recovered")
3637
ErrWithClockNil = fmt.Errorf("gocron: WithClock: clock must not be nil")
3738
ErrWithDistributedElectorNil = fmt.Errorf("gocron: WithDistributedElector: elector must not be nil")
3839
ErrWithDistributedLockerNil = fmt.Errorf("gocron: WithDistributedLocker: locker must not be nil")

examples/elector/main.go

-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ func main() {
5151
log.Println("run job")
5252
}),
5353
)
54-
5554
if err != nil {
5655
log.Println(err)
5756
return

executor.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ func (e *executor) runJob(j internalJob, jIn jobIn) {
368368
}
369369

370370
startTime := time.Now()
371-
err := callJobFuncWithParams(j.function, j.parameters...)
371+
err := e.callJobWithRecover(j)
372372
if e.monitor != nil {
373373
e.monitor.RecordJobTiming(startTime, time.Now(), j.id, j.name, j.tags)
374374
}
@@ -381,6 +381,19 @@ func (e *executor) runJob(j internalJob, jIn jobIn) {
381381
}
382382
}
383383

384+
func (e *executor) callJobWithRecover(j internalJob) (err error) {
385+
defer func() {
386+
if recoverData := recover(); recoverData != nil {
387+
_ = callJobFuncWithParams(j.afterJobRunsWithPanic, j.id, j.name, recoverData)
388+
389+
// if panic is occurred, we should return an error
390+
err = ErrPanicRecovered
391+
}
392+
}()
393+
394+
return callJobFuncWithParams(j.function, j.parameters...)
395+
}
396+
384397
func (e *executor) incrementJobCounter(j internalJob, status JobStatus) {
385398
if e.monitor != nil {
386399
e.monitor.IncrementJob(j.id, j.name, j.tags, status)

job.go

+17-4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type internalJob struct {
4242
afterJobRuns func(jobID uuid.UUID, jobName string)
4343
beforeJobRuns func(jobID uuid.UUID, jobName string)
4444
afterJobRunsWithError func(jobID uuid.UUID, jobName string, err error)
45+
afterJobRunsWithPanic func(jobID uuid.UUID, jobName string, recoverData any)
4546
afterLockError func(jobID uuid.UUID, jobName string, err error)
4647

4748
locker Locker
@@ -604,6 +605,18 @@ func WithTags(tags ...string) JobOption {
604605
// listeners that can be used to listen for job events.
605606
type EventListener func(*internalJob) error
606607

608+
// BeforeJobRuns is used to listen for when a job is about to run and
609+
// then run the provided function.
610+
func BeforeJobRuns(eventListenerFunc func(jobID uuid.UUID, jobName string)) EventListener {
611+
return func(j *internalJob) error {
612+
if eventListenerFunc == nil {
613+
return ErrEventListenerFuncNil
614+
}
615+
j.beforeJobRuns = eventListenerFunc
616+
return nil
617+
}
618+
}
619+
607620
// AfterJobRuns is used to listen for when a job has run
608621
// without an error, and then run the provided function.
609622
func AfterJobRuns(eventListenerFunc func(jobID uuid.UUID, jobName string)) EventListener {
@@ -628,14 +641,14 @@ func AfterJobRunsWithError(eventListenerFunc func(jobID uuid.UUID, jobName strin
628641
}
629642
}
630643

631-
// BeforeJobRuns is used to listen for when a job is about to run and
632-
// then run the provided function.
633-
func BeforeJobRuns(eventListenerFunc func(jobID uuid.UUID, jobName string)) EventListener {
644+
// AfterJobRunsWithPanic is used to listen for when a job has run and
645+
// returned panicked recover data, and then run the provided function.
646+
func AfterJobRunsWithPanic(eventListenerFunc func(jobID uuid.UUID, jobName string, recoverData any)) EventListener {
634647
return func(j *internalJob) error {
635648
if eventListenerFunc == nil {
636649
return ErrEventListenerFuncNil
637650
}
638-
j.beforeJobRuns = eventListenerFunc
651+
j.afterJobRunsWithPanic = eventListenerFunc
639652
return nil
640653
}
641654
}

job_test.go

+38-3
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,13 @@ func TestWithEventListeners(t *testing.T) {
416416
nil,
417417
nil,
418418
},
419+
{
420+
"beforeJobRuns",
421+
[]EventListener{
422+
BeforeJobRuns(func(_ uuid.UUID, _ string) {}),
423+
},
424+
nil,
425+
},
419426
{
420427
"afterJobRuns",
421428
[]EventListener{
@@ -431,9 +438,9 @@ func TestWithEventListeners(t *testing.T) {
431438
nil,
432439
},
433440
{
434-
"beforeJobRuns",
441+
"afterJobRunsWithPanic",
435442
[]EventListener{
436-
BeforeJobRuns(func(_ uuid.UUID, _ string) {}),
443+
AfterJobRunsWithPanic(func(_ uuid.UUID, _ string, _ any) {}),
437444
},
438445
nil,
439446
},
@@ -487,13 +494,16 @@ func TestWithEventListeners(t *testing.T) {
487494
return
488495
}
489496
var count int
497+
if ij.beforeJobRuns != nil {
498+
count++
499+
}
490500
if ij.afterJobRuns != nil {
491501
count++
492502
}
493503
if ij.afterJobRunsWithError != nil {
494504
count++
495505
}
496-
if ij.beforeJobRuns != nil {
506+
if ij.afterJobRunsWithPanic != nil {
497507
count++
498508
}
499509
if ij.afterLockError != nil {
@@ -633,3 +643,28 @@ func TestJob_NextRuns(t *testing.T) {
633643
})
634644
}
635645
}
646+
647+
func TestJob_PanicOccurred(t *testing.T) {
648+
gotCh := make(chan any)
649+
s := newTestScheduler(t)
650+
_, err := s.NewJob(
651+
DurationJob(10*time.Millisecond),
652+
NewTask(func() {
653+
a := 0
654+
_ = 1 / a
655+
}),
656+
WithEventListeners(
657+
AfterJobRunsWithPanic(func(_ uuid.UUID, _ string, recoverData any) {
658+
gotCh <- recoverData
659+
}),
660+
),
661+
)
662+
require.NoError(t, err)
663+
664+
s.Start()
665+
got := <-gotCh
666+
require.EqualError(t, got.(error), "runtime error: integer divide by zero")
667+
668+
require.NoError(t, s.Shutdown())
669+
close(gotCh)
670+
}

0 commit comments

Comments
 (0)