Skip to content

Commit

Permalink
cc/cron: factor hour/dow denylists into schedule
Browse files Browse the repository at this point in the history
Recalculate the hour and dow manually factoring in any excluded hours or dows to accurately calculate the next run time on the first try.

Signed-off-by: SoggySaussages <[email protected]>
  • Loading branch information
SoggySaussages committed Nov 21, 2024
1 parent 38c6d19 commit ab9c6e8
Showing 1 changed file with 24 additions and 7 deletions.
31 changes: 24 additions & 7 deletions customcommands/interval.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,32 @@ func CalcNextRunTime(cc *models.CustomCommand, now time.Time) time.Time {
// somehow this got past validation, can't run
return time.Time{}
}
maybeNextRun := time.Now().UTC()
for i := 0; i < 200; i++ { // set an upper limit on retries
maybeNextRun = cronSchedule.Next(maybeNextRun)
nextRunBlacklisted := common.ContainsInt64Slice(cc.TimeTriggerExcludingDays, int64(maybeNextRun.Weekday())) || common.ContainsInt64Slice(cc.TimeTriggerExcludingHours, int64(maybeNextRun.Hour()))
if !nextRunBlacklisted {
break
specSchedule := cronSchedule.(*cron.SpecSchedule)
const hoursInADay = 24
const daysInAWeek = 7
var newHoursScheduledBitset uint64
var newDaysScheduledBitset uint64
for hourOfDay := range hoursInADay {
hourOfDayBitVal := uint64(1) << hourOfDay
hourPresentInSchedule := specSchedule.Hour&hourOfDayBitVal == hourOfDayBitVal
if hourPresentInSchedule && !common.ContainsInt64Slice(cc.TimeTriggerExcludingHours, int64(hourOfDay)) {
newHoursScheduledBitset = newHoursScheduledBitset | hourOfDayBitVal
}
}
tNext = maybeNextRun
for dayOfWeek := range daysInAWeek {
dayOfWeekBitVal := uint64(1) << dayOfWeek
dayPresentInSchedule := specSchedule.Dow&dayOfWeekBitVal == dayOfWeekBitVal
if dayPresentInSchedule && !common.ContainsInt64Slice(cc.TimeTriggerExcludingHours, int64(dayOfWeek)) {
newDaysScheduledBitset = newDaysScheduledBitset | dayOfWeekBitVal
}
}
specSchedule.Hour = newHoursScheduledBitset
specSchedule.Dow = newDaysScheduledBitset
if specSchedule.Hour == 0 || specSchedule.Dow == 0 {
// this can never run
return time.Time{}
}
tNext = specSchedule.Next(time.Now().UTC())
}

return tNext
Expand Down

0 comments on commit ab9c6e8

Please sign in to comment.