diff --git a/pkg/fleetautoscalers/fleetautoscalers.go b/pkg/fleetautoscalers/fleetautoscalers.go index 9bf8da7b04..9049b975f5 100644 --- a/pkg/fleetautoscalers/fleetautoscalers.go +++ b/pkg/fleetautoscalers/fleetautoscalers.go @@ -418,9 +418,7 @@ func applyChainPolicy(c autoscalingv1.ChainPolicy, f *agonesv1.Fleet, gameServer // isScheduleActive checks if a chain entry's is active and returns a boolean, true if active, false otherwise func isScheduleActive(s *autoscalingv1.SchedulePolicy, currentTime time.Time) bool { - // When retrieving the next available cronTime it returns the next minute e.g. if you want a policy to run every minute (all the time) - // If the current time is 1:00, the next start time returned will be 1:01, thus we use a cronDelta of 90 seconds to - // adjust to the minute delta (since the next start time will always be ahead of the current time by 1 minute when the schedule is active). + // Used for checking ahead of the schedule for daylight savings purposes cronDelta := (time.Minute * -1) + (time.Second * -30) // If the current time is before the start time, the schedule is inactive so return false @@ -443,23 +441,25 @@ func isScheduleActive(s *autoscalingv1.SchedulePolicy, currentTime time.Time) bo location, _ := time.LoadLocation(s.ActivePeriod.Timezone) startCron, _ := cron.ParseStandard(s.ActivePeriod.StartCron) duration, _ := time.ParseDuration(s.ActivePeriod.Duration) - nextStartTime := startCron.Next(currentTime.In(location)) + + // Get the current time - duration + currentTimeMinusDuration := currentTime.Add(duration * -1) + // Take (current time - duration) to get the first available start time + cronStartTime := startCron.Next(currentTimeMinusDuration.In(location)) + // Take the (cronStartTime + duration) to get the end time + cronEndTime := cronStartTime.Add(duration) // If there's an err, then the duration field is empty, meaning duration is indefinite if s.ActivePeriod.Duration == "" { duration = 0 // Indefinite duration if not set } - // If the current time is after the next start time, and the duration is indefinite or the current time is before the next start time + duration, - // then return true. - // e.g. - // startCron = * * * * * - // currentTime = 2024-08-01T14:30:00Z // 2:30 PM UTC on August 1, 2024 - // nextStartTime = 2024-08-01T14:31:00Z // 2:31 PM UTC on August 1, 2024 - // duration = 1 hour - // cronDelta = 1 Minute Delta 30 seconds - // This would return true since the currentTime > nextStartTime - cronDelta AND the currentTime < nextStartTime + duration. - if currentTime.After(nextStartTime.Add(cronDelta)) && (duration == 0 || currentTime.Before(nextStartTime.Add(duration))) { + // If the current time is after the cronStartTime - 90 seconds (for daylight saving purposes) AND the current time before the cronEndTime + // then return true + // Example: startCron = 0 14 * * * // 2:00 PM Everyday | duration = 1 hr | cronDelta = 90 seconds | currentTime = 2024-08-01T14:30:00Z | currentTimeMinusDuration = 2024-08-01T13:30:00Z + // then cronStartTime = 2024-08-01T14:00:00Z and cronEndTime = 2024-08-01T15:00:00Z + // and since currentTime > cronStartTime + cronDelta AND currentTime < cronEndTime, we return true + if currentTime.After(cronStartTime.Add(cronDelta)) && currentTime.Before(cronEndTime) { return true }