Mercurial > servermonitor
diff ServerMonitor/Objects/Schedule.cs @ 17:68d7834dc28e
More comments.
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Sat, 25 May 2019 15:14:26 -0400 |
parents | d92176c5398a |
children | 2342e9459444 |
line wrap: on
line diff
--- a/ServerMonitor/Objects/Schedule.cs Tue Apr 30 20:40:58 2019 -0400 +++ b/ServerMonitor/Objects/Schedule.cs Sat May 25 15:14:26 2019 -0400 @@ -2,10 +2,22 @@ namespace ServerMonitorApp { + /// <summary>Schedule to control when a check is automatically executed.<summary> public class Schedule { + // Required empty constructor for XML serialization. public Schedule() { } + /// <summary>Schedule constructor</summary> + /// <param name="units">The time units to use.</param> + /// <param name="frequency">How frequently to run the check.</param> + /// <param name="startTime">Time of day the check should begin running.</param> + /// <param name="endTime">Time of day the check should stop running.</param> + /// <remarks> + /// If endTime is before startTime, then the endTime is interpreted as being on the next day. + /// For example, if startTime = 17:00 and endTime is 8:00, then the check will start running + /// at 17:00 and stop running at 8:00 the next day. + /// </remarks> public Schedule(FrequencyUnits units, int frequency, TimeSpan startTime, TimeSpan endTime) { Units = units; @@ -14,32 +26,57 @@ EndTime = endTime; } + /// <summary>How often the check should be executed.</summary> public int Frequency { get; set; } + /// <summary>The time units used to interpret the frequency.</summary> public FrequencyUnits Units { get; set; } + /// <summary>Time of day the check should begin running.</summary> public TimeSpan StartTime { get; set; } + /// <summary>Time of day the check should stop running.</summary> public TimeSpan EndTime { get; set; } + /// <summary>Given the last time a check was scheduled to run, calculates the next time in the future it should run.</summary> + /// <param name="lastScheduledTime">The last time a check was scheduled to run.</param> public DateTime GetNextTime(DateTime lastScheduledTime) { return GetNextTime(lastScheduledTime, DateTime.Now); } + /// <summary>Given the last time a check was scheduled to run, calculates the next time after the given date it should run.</summary> + /// <param name="lastScheduledTime">The last time a check was scheduled to run.</param> + /// <param name="minStartTime">The earliest allowed time to return.</param> + /// <remarks> + /// The next execution time of a check cannot necessarily be determined by taking the + /// last execution time and adding the configured number of time units. The computer might + /// have been asleep or the program might have not been running, so the next date might + /// be in the past. + /// + /// To best follow the schedule, we take the last execution time and fast-forward time + /// by adding the configured time interval until we get a resulting time that is in the future. + /// For example, suppose a check is scheduled to run every 5 minutes starting at 7:00. + /// The check last ran at 7:40, and the computer was suspended shortly thereafter and resumed + /// at 8:28. The next execution time is determined by adding 5 minutes to 7:40 until we obtain + /// a time after 8:28, in this case, 8:30. + /// </remarks> public DateTime GetNextTime(DateTime lastScheduledTime, DateTime minStartTime) { + // Start by setting the next time to the last time the check was run. DateTime nextTime = lastScheduledTime; if (Units == FrequencyUnits.Day) { + // If the check is scheduled only once a day, simply add days until we find a time in the future. while (nextTime < minStartTime) nextTime = nextTime.AddDays(Frequency).Date.Add(StartTime); } else { - // If the last run time was more than a day ago, fast-forward to reduce the number of loops + // If the last run time was more than a day ago, fast-forward a day at a time to reduce the number of loops. if (nextTime < minStartTime.AddHours(-24)) nextTime = minStartTime.Date.Add(StartTime).AddHours(-24); + // Add the configured time interval to the last run time until we obtain a time in the future. while (nextTime < minStartTime) { switch (Units) @@ -50,15 +87,25 @@ default: throw new InvalidOperationException("Unexpected frequency units: " + Units); } } + // Now we have the next date and time, but we don't know yet if it is within + // the active times of day the check is allowed to run between. if (StartTime < EndTime) { + // The allowed start and end times are on the same day. + // If the next scheduled time is too early (before the allowed start time), + // wait to run it until the start time happens. if (nextTime.TimeOfDay < StartTime) nextTime = nextTime.Date + StartTime; + // If the next scheduled time is too late (after the allowed end time), + // wait to run it until the start time happens on the following day. else if (nextTime.TimeOfDay > EndTime) nextTime = nextTime.Date.AddDays(1) + StartTime; } else if (nextTime.TimeOfDay > EndTime && nextTime.TimeOfDay < StartTime) { + // The allowed start time is on the day after the allowed end time, + // and the next scheduled time is too early (before the allowed start time). + // Wait to run the check until the allowed start time happens. nextTime = nextTime.Date + StartTime; } } @@ -71,5 +118,6 @@ } } + /// <summary>Units of time that a check can be scheduled to run in intervals of.</summary> public enum FrequencyUnits { Second, Minute, Hour, Day } } \ No newline at end of file