From 31b4eca24d3df7005545afe70279b5c4dd04a319 Mon Sep 17 00:00:00 2001 From: John Roesler Date: Fri, 3 Jan 2025 10:34:58 -0600 Subject: [PATCH] working to handle edge cases where a job can be run twice, unexpectedly --- job.go | 8 ++++---- scheduler.go | 11 ++++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/job.go b/job.go index 2ea8e91..2974733 100644 --- a/job.go +++ b/job.go @@ -818,7 +818,7 @@ func (d dailyJob) next(lastRun time.Time) time.Time { } firstPass = false - startNextDay := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day()+int(d.interval), 0, 0, 0, lastRun.Nanosecond(), lastRun.Location()) + startNextDay := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day()+int(d.interval), 0, 0, 0, 0, lastRun.Location()) return d.nextDay(startNextDay, firstPass) } @@ -826,7 +826,7 @@ func (d dailyJob) nextDay(lastRun time.Time, firstPass bool) time.Time { for _, at := range d.atTimes { // sub the at time hour/min/sec onto the lastScheduledRun's values // to use in checks to see if we've got our next run time - atDate := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day(), at.Hour(), at.Minute(), at.Second(), lastRun.Nanosecond(), lastRun.Location()) + atDate := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day(), at.Hour(), at.Minute(), at.Second(), 0, lastRun.Location()) if firstPass && atDate.After(lastRun) { // checking to see if it is after i.e. greater than, @@ -872,7 +872,7 @@ func (w weeklyJob) nextWeekDayAtTime(lastRun time.Time, firstPass bool) time.Tim for _, at := range w.atTimes { // sub the at time hour/min/sec onto the lastScheduledRun's values // to use in checks to see if we've got our next run time - atDate := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day()+int(weekDayDiff), at.Hour(), at.Minute(), at.Second(), lastRun.Nanosecond(), lastRun.Location()) + atDate := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day()+int(weekDayDiff), at.Hour(), at.Minute(), at.Second(), 0, lastRun.Location()) if firstPass && atDate.After(lastRun) { // checking to see if it is after i.e. greater than, @@ -940,7 +940,7 @@ func (m monthlyJob) nextMonthDayAtTime(lastRun time.Time, days []int, firstPass for _, at := range m.atTimes { // sub the day, and the at time hour/min/sec onto the lastScheduledRun's values // to use in checks to see if we've got our next run time - atDate := time.Date(lastRun.Year(), lastRun.Month(), day, at.Hour(), at.Minute(), at.Second(), lastRun.Nanosecond(), lastRun.Location()) + atDate := time.Date(lastRun.Year(), lastRun.Month(), day, at.Hour(), at.Minute(), at.Second(), 0, lastRun.Location()) if atDate.Month() != lastRun.Month() { // this check handles if we're setting a day not in the current month diff --git a/scheduler.go b/scheduler.go index 9827f0c..19864c6 100644 --- a/scheduler.go +++ b/scheduler.go @@ -331,7 +331,7 @@ func (s *scheduler) selectExecJobsOutForRescheduling(id uuid.UUID) { return } - scheduleFrom := j.lastRun + var scheduleFrom time.Time if len(j.nextScheduled) > 0 { // always grab the last element in the slice as that is the furthest // out in the future and the time from which we want to calculate @@ -362,6 +362,15 @@ func (s *scheduler) selectExecJobsOutForRescheduling(id uuid.UUID) { } } + if slices.Contains(j.nextScheduled, next) { + // if the next value is a duplicate of what's already in the nextScheduled slice, for example: + // - the job is being rescheduled off the same next run value as before + // increment to the next, next value + for slices.Contains(j.nextScheduled, next) { + next = j.next(next) + } + } + // Clean up any existing timer to prevent leaks if j.timer != nil { j.timer.Stop()