/// <summary> /// Public only to allow HangFire to access it /// </summary> /// <param name="adviceId"></param> public void CreateOrUpdateJob(int adviceId) { var advice = AdviceRepository.GetByKey(adviceId); if (advice == null || advice.Scheduling == null || advice.AlarmDate == null) { throw new ArgumentException(nameof(adviceId) + " does not point to a valid id or points to an advice without alarm date or scheduling"); } var adviceAlarmDate = advice.AlarmDate.Value; var adviceScheduling = advice.Scheduling.Value; var adviceTriggers = AdviceTriggerFactory.CreateFrom(adviceAlarmDate, adviceScheduling); foreach (var adviceTrigger in adviceTriggers) { var prefix = advice.JobId; var jobId = adviceTrigger.PartitionId.Match(partitionId => CreatePartitionJobId(prefix, partitionId), () => prefix); HangfireApi.AddOrUpdateRecurringJob(jobId, () => SendAdvice(adviceId), adviceTrigger.Cron); } if (advice.StopDate.HasValue) { //Schedule deactivation to happen the day after the stop date (stop date is "last day alive" for the advice) HangfireApi.Schedule(() => DeactivateById(advice.Id), new DateTimeOffset(advice.StopDate.Value.Date.AddDays(1))); } //If time has passed the trigger time, Hangfire will not fire until the next trigger data so we must force it. if (adviceAlarmDate.Date.Equals(OperationClock.Now.Date)) { switch (adviceScheduling) { case Scheduling.Day: case Scheduling.Week: case Scheduling.Month: case Scheduling.Year: case Scheduling.Quarter: case Scheduling.Semiannual: var mustScheduleAdviceToday = advice.AdviceSent.Where(x => x.AdviceSentDate.Date == adviceAlarmDate.Date).Any() == false && WillTriggerInvokeToday() == false; if (mustScheduleAdviceToday) { //Send the first advice now HangfireApi.Schedule(() => SendAdvice(adviceId)); } break; //Intentional fallthrough - no corrections here case Scheduling.Hour: case Scheduling.Immediate: default: break; } } }
public void CreateFromAlarmDateAndScheduleReturns_With_Monthly_Interval_HandlesAlarmDate_InLeap_Year() { //Arrange var leapYearDate = new DateTime(2020, 2, 29); var expectedPartitions = Enumerable.Range(0, 12).ToList(); var expectedCronJobs = CreateExpectedCronForMonthlyInterval(leapYearDate.Year, leapYearDate.Day, true); //Act var adviceTriggers = AdviceTriggerFactory.CreateFrom(leapYearDate, Scheduling.Month).ToList(); //Assert AssertCreatedJobs(adviceTriggers, expectedPartitions, expectedCronJobs); }
public void CreateFromAlarmDateAndScheduleReturns_12_Triggers_For_Monthly_Trigger_With_Day(int day) { //Arrange var year = 2000; var alarmDate = new DateTime(year, 3, day); var expectedPartitions = Enumerable.Range(0, 12).ToList(); var expectedCronJobs = CreateExpectedCronForMonthlyInterval(year, day, true); //Act var adviceTriggers = AdviceTriggerFactory.CreateFrom(alarmDate, Scheduling.Month).ToList(); //Assert AssertCreatedJobs(adviceTriggers, expectedPartitions, expectedCronJobs); }
public void CreateFromAlarmDateAndScheduleReturns_With_Yearly_Interval_HandlesAlarmDate_InLeap_Year() { //Arrange var leapYearDate = new DateTime(2020, 2, 29); var expectedInterval = CronStringHelper.CronPerInterval(Scheduling.Year, leapYearDate, true); //Act var adviceTriggers = AdviceTriggerFactory.CreateFrom(leapYearDate, Scheduling.Year).ToList(); //Assert var adviceTrigger = Assert.Single(adviceTriggers); Assert.Equal(expectedInterval, adviceTrigger.Cron); }
public void CreateFromAlarmDateAndScheduleReturns_1_Trigger_With_LastDayInMonth_If_31_Is_Selected(Scheduling scheduling, int month, int day) { //Arrange var alarmDate = new DateTime(2000, month, day); var expectedInterval = CronStringHelper.CronPerInterval(scheduling, new DateTime(2000, month, day), true); //Act var adviceTriggers = AdviceTriggerFactory.CreateFrom(alarmDate, scheduling).ToList(); //Assert var adviceTrigger = Assert.Single(adviceTriggers); Assert.False(adviceTrigger.PartitionId.HasValue); Assert.Equal(expectedInterval, adviceTrigger.Cron); }
public void CreateFromAlarmDateAndScheduleReturns_2_Triggers_For_SemiAnnualTrigger_Trigger_With_Day_Which_Conflicts_With_February(int month, int day) { //Arrange var alarmDate = new DateTime(2000, month, day); var expectedPartitions = Enumerable.Range(0, 2).ToList(); var expectedCronJobs = new[] { CronStringHelper.CronPerInterval(Scheduling.Year, new DateTime(2000, 2, 28), true), CronStringHelper.CronPerInterval(Scheduling.Year, new DateTime(2000, 8, day)) }; //Act var adviceTriggers = AdviceTriggerFactory.CreateFrom(alarmDate, Scheduling.Semiannual).ToList(); //Assert AssertCreatedJobs(adviceTriggers, expectedPartitions, expectedCronJobs); }
public void CreateFromAlarmDateAndScheduleReturns_With_SemiAnnual_Interval_HandlesAlarmDate_InLeap_Year() { //Arrange var leapYearDate = new DateTime(2020, 2, 29); var expectedPartitions = Enumerable.Range(0, 2).ToList(); var expectedCronJobs = new[] { CronStringHelper.CronPerInterval(Scheduling.Year, leapYearDate, true), CronStringHelper.CronPerInterval(Scheduling.Year, new DateTime(leapYearDate.Year, leapYearDate.Month + 6, leapYearDate.Day)) }; //Act var adviceTriggers = AdviceTriggerFactory.CreateFrom(leapYearDate, Scheduling.Semiannual).ToList(); //Assert AssertCreatedJobs(adviceTriggers, expectedPartitions, expectedCronJobs); }