Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(event listener): introduce BeforeJobRunsSkipIfBeforeFuncErrors as a new Eventlistener #813

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/file_formatting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ jobs:
uses: actions/checkout@v4
- name: verify example_test.go
run: |
grep "^func " example_test.go | sort -c
grep "^func [a-z-A-Z]" example_test.go | sort -c
FalcoSuessgott marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ fmt:
@go list -f {{.Dir}} ./... | xargs -I{} gofmt -w -s {}

lint:
@grep "^func " example_test.go | sort -c
@grep "^func [a-zA-Z]" example_test.go | sort -c
@golangci-lint run

test:
Expand Down
23 changes: 23 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,29 @@ func ExampleBeforeJobRuns() {
)
}

func ExampleBeforeJobRunsSkipIfBeforeFuncErrors() {
s, _ := gocron.NewScheduler()
defer func() { _ = s.Shutdown() }()

_, _ = s.NewJob(
gocron.DurationJob(
time.Second,
),
gocron.NewTask(
func() {
fmt.Println("Will never run, because before job func errors")
},
),
gocron.WithEventListeners(
gocron.BeforeJobRunsSkipIfBeforeFuncErrors(
func(jobID uuid.UUID, jobName string) error {
return fmt.Errorf("error")
},
),
),
)
}

func ExampleCronJob() {
s, _ := gocron.NewScheduler()
defer func() { _ = s.Shutdown() }()
Expand Down
14 changes: 13 additions & 1 deletion executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,16 +389,28 @@ func (e *executor) runJob(j internalJob, jIn jobIn) {
}
defer func() { _ = lock.Unlock(j.ctx) }()
}

_ = callJobFuncWithParams(j.beforeJobRuns, j.id, j.name)

err := callJobFuncWithParams(j.beforeJobRunsSkipIfBeforeFuncErrors, j.id, j.name)
if err != nil {
e.sendOutForRescheduling(&jIn)

select {
case e.jobsOutCompleted <- j.id:
case <-e.ctx.Done():
}

return
}

e.sendOutForRescheduling(&jIn)
select {
case e.jobsOutCompleted <- j.id:
case <-e.ctx.Done():
}

startTime := time.Now()
var err error
if j.afterJobRunsWithPanic != nil {
err = e.callJobWithRecover(j)
} else {
Expand Down
26 changes: 20 additions & 6 deletions job.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ type internalJob struct {
startImmediately bool
stopTime time.Time
// event listeners
afterJobRuns func(jobID uuid.UUID, jobName string)
beforeJobRuns func(jobID uuid.UUID, jobName string)
afterJobRunsWithError func(jobID uuid.UUID, jobName string, err error)
afterJobRunsWithPanic func(jobID uuid.UUID, jobName string, recoverData any)
afterLockError func(jobID uuid.UUID, jobName string, err error)
disabledLocker bool
afterJobRuns func(jobID uuid.UUID, jobName string)
beforeJobRuns func(jobID uuid.UUID, jobName string)
beforeJobRunsSkipIfBeforeFuncErrors func(jobID uuid.UUID, jobName string) error
afterJobRunsWithError func(jobID uuid.UUID, jobName string, err error)
afterJobRunsWithPanic func(jobID uuid.UUID, jobName string, recoverData any)
afterLockError func(jobID uuid.UUID, jobName string, err error)
disabledLocker bool

locker Locker
}
Expand Down Expand Up @@ -724,6 +725,19 @@ func BeforeJobRuns(eventListenerFunc func(jobID uuid.UUID, jobName string)) Even
}
}

// BeforeJobRunsSkipIfBeforeFuncErrors is used to listen for when a job is about to run and
// then runs the provided function. If the provided function returns an error, the job will be
// rescheduled and the current run will be skipped.
func BeforeJobRunsSkipIfBeforeFuncErrors(eventListenerFunc func(jobID uuid.UUID, jobName string) error) EventListener {
return func(j *internalJob) error {
if eventListenerFunc == nil {
return ErrEventListenerFuncNil
}
j.beforeJobRunsSkipIfBeforeFuncErrors = eventListenerFunc
return nil
}
}

// AfterJobRuns is used to listen for when a job has run
// without an error, and then run the provided function.
func AfterJobRuns(eventListenerFunc func(jobID uuid.UUID, jobName string)) EventListener {
Expand Down
7 changes: 7 additions & 0 deletions job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,13 @@ func TestWithEventListeners(t *testing.T) {
},
ErrEventListenerFuncNil,
},
{
"nil before job runs error listener",
[]EventListener{
BeforeJobRunsSkipIfBeforeFuncErrors(nil),
},
ErrEventListenerFuncNil,
},
}

for _, tt := range tests {
Expand Down
Loading