/// <summary> /// Returns a list of Dates that are the next fire times of a /// <see cref="ITrigger" />. /// The input trigger will be cloned before any work is done, so you need /// not worry about its state being altered by this method. /// </summary> /// <param name="trigg">The trigger upon which to do the work</param> /// <param name="cal">The calendar to apply to the trigger's schedule</param> /// <param name="numTimes">The number of next fire times to produce</param> public static IReadOnlyList <DateTimeOffset> ComputeFireTimes(IOperableTrigger trigg, ICalendar?cal, int numTimes) { List <DateTimeOffset> lst = new List <DateTimeOffset>(); IOperableTrigger t = (IOperableTrigger)trigg.Clone(); if (t.GetNextFireTimeUtc() == null || !t.GetNextFireTimeUtc().HasValue) { t.ComputeFirstFireTimeUtc(cal); } for (int i = 0; i < numTimes; i++) { DateTimeOffset?d = t.GetNextFireTimeUtc(); if (d.HasValue) { lst.Add(d.Value); t.Triggered(cal); } else { break; } } return(lst.AsReadOnly()); }
public void TestAcquireTriggers() { InitJobStore(); ISchedulerSignaler schedSignaler = new SampleSignaler(); ITypeLoadHelper loadHelper = new SimpleTypeLoadHelper(); loadHelper.Initialize(); var store = new RavenJobStore(); store.Initialize(loadHelper, schedSignaler); store.SchedulerStarted(); // Setup: Store jobs and triggers. DateTime startTime0 = DateTime.UtcNow.AddMinutes(1).ToUniversalTime(); // a min from now. for (int i = 0; i < 10; i++) { DateTime startTime = startTime0.AddMinutes(i * 1); // a min apart IJobDetail job = JobBuilder.Create <NoOpJob>().WithIdentity("job" + i).Build(); SimpleScheduleBuilder schedule = SimpleScheduleBuilder.RepeatMinutelyForever(2); IOperableTrigger trigger = (IOperableTrigger)TriggerBuilder.Create().WithIdentity("trigger" + i).WithSchedule(schedule).ForJob(job).StartAt(startTime).Build(); // Manually trigger the first fire time computation that scheduler would do. Otherwise // the store.acquireNextTriggers() will not work properly. DateTimeOffset?fireTime = trigger.ComputeFirstFireTimeUtc(null); Assert.AreEqual(true, fireTime != null); store.StoreJobAndTrigger(job, trigger); } // Test acquire one trigger at a time for (int i = 0; i < 10; i++) { DateTimeOffset noLaterThan = startTime0.AddMinutes(i); int maxCount = 1; TimeSpan timeWindow = TimeSpan.Zero; IList <IOperableTrigger> triggers = store.AcquireNextTriggers(noLaterThan, maxCount, timeWindow); Assert.AreEqual(1, triggers.Count); Assert.AreEqual("trigger" + i, triggers[0].Key.Name); // Let's remove the trigger now. store.RemoveJob(triggers[0].JobKey); } }
public void TestAcquireTriggersInBatch() { ISchedulerSignaler schedSignaler = new SampleSignaler(); ITypeLoadHelper loadHelper = new SimpleTypeLoadHelper(); loadHelper.Initialize(); RAMJobStore store = new RAMJobStore(); store.Initialize(loadHelper, schedSignaler); // Setup: Store jobs and triggers. DateTimeOffset startTime0 = DateTimeOffset.UtcNow.AddMinutes(1); // a min from now. for (int i = 0; i < 10; i++) { DateTimeOffset startTime = startTime0.AddMinutes(i); // a min apart IJobDetail job = JobBuilder.Create <NoOpJob>().WithIdentity("job" + i).Build(); SimpleScheduleBuilder schedule = SimpleScheduleBuilder.RepeatMinutelyForever(2); IOperableTrigger trigger = (IOperableTrigger)TriggerBuilder.Create().WithIdentity("job" + i).WithSchedule(schedule).ForJob(job).StartAt(startTime).Build(); // Manually trigger the first fire time computation that scheduler would do. Otherwise // the store.acquireNextTriggers() will not work properly. DateTimeOffset?fireTime = trigger.ComputeFirstFireTimeUtc(null); Assert.AreEqual(true, fireTime != null); store.StoreJobAndTrigger(job, trigger); } // Test acquire batch of triggers at a time DateTimeOffset noLaterThan = startTime0.AddMinutes(10); int maxCount = 7; TimeSpan timeWindow = TimeSpan.FromMinutes(8); IList <IOperableTrigger> triggers = store.AcquireNextTriggers(noLaterThan, maxCount, timeWindow); Assert.AreEqual(7, triggers.Count); for (int i = 0; i < 7; i++) { Assert.AreEqual("job" + i, triggers[i].Key.Name); } }
/// <summary> /// Compute the <see cref="DateTimeOffset" /> that is 1 second after the Nth firing of /// the given <see cref="ITrigger" />, taking the trigger's associated /// <see cref="ICalendar" /> into consideration. /// </summary> /// <remarks> /// The input trigger will be cloned before any work is done, so you need /// not worry about its state being altered by this method. /// </remarks> /// <param name="trigger">The trigger upon which to do the work</param> /// <param name="calendar">The calendar to apply to the trigger's schedule</param> /// <param name="numberOfTimes">The number of next fire times to produce</param> /// <returns>the computed Date, or null if the trigger (as configured) will not fire that many times</returns> public static DateTimeOffset?ComputeEndTimeToAllowParticularNumberOfFirings(IOperableTrigger trigger, ICalendar?calendar, int numberOfTimes) { IOperableTrigger t = (IOperableTrigger)trigger.Clone(); if (t.GetNextFireTimeUtc() == null) { t.ComputeFirstFireTimeUtc(calendar); } int c = 0; DateTimeOffset?endTime = null; for (int i = 0; i < numberOfTimes; i++) { DateTimeOffset?d = t.GetNextFireTimeUtc(); if (d != null) { c++; t.Triggered(calendar); if (c == numberOfTimes) { endTime = d; } } else { break; } } if (endTime == null) { return(null); } endTime = endTime.Value.AddSeconds(1); return(endTime); }
/// <summary> /// Returns a list of Dates that are the next fire times of a <see cref="ITrigger" /> /// that fall within the given date range. The input trigger will be cloned /// before any work is done, so you need not worry about its state being /// altered by this method. /// <para> /// NOTE: if this is a trigger that has previously fired within the given /// date range, then firings which have already occurred will not be listed /// in the output List. /// </para> /// </summary> /// <param name="trigg">The trigger upon which to do the work</param> /// <param name="cal">The calendar to apply to the trigger's schedule</param> /// <param name="from">The starting date at which to find fire times</param> /// <param name="to">The ending date at which to stop finding fire times</param> public static IReadOnlyList <DateTimeOffset> ComputeFireTimesBetween(IOperableTrigger trigg, ICalendar?cal, DateTimeOffset from, DateTimeOffset to) { List <DateTimeOffset> lst = new List <DateTimeOffset>(); IOperableTrigger t = (IOperableTrigger)trigg.Clone(); if (t.GetNextFireTimeUtc() == null || !t.GetNextFireTimeUtc().HasValue) { t.StartTimeUtc = from; t.EndTimeUtc = to; t.ComputeFirstFireTimeUtc(cal); } // TODO: this method could be more efficient by using logic specific // to the type of trigger ... while (true) { DateTimeOffset?d = t.GetNextFireTimeUtc(); if (d.HasValue) { if (d.Value < from) { t.Triggered(cal); continue; } if (d.Value > to) { break; } lst.Add(d.Value); t.Triggered(cal); } else { break; } } return(lst.AsReadOnly()); }
// Adapted from https://github.com/quartznet/quartznet/blob/master/src/Quartz/TriggerUtils.cs public static int ComputeFireTimeCountBetween(IOperableTrigger trigg, ICalendar cal, DateTimeOffset from, DateTimeOffset to) { int count = 0; IOperableTrigger t = (IOperableTrigger)trigg.Clone(); if (t.GetNextFireTimeUtc() == null || !t.GetNextFireTimeUtc().HasValue) { t.StartTimeUtc = from; t.EndTimeUtc = to; t.ComputeFirstFireTimeUtc(cal); } // TODO: this method could be more efficient by using logic specific // to the type of trigger ... while (true) { DateTimeOffset?d = t.GetNextFireTimeUtc(); if (d.HasValue) { if (d.Value < from) { t.Triggered(cal); continue; } if (d.Value > to) { break; } count++; t.Triggered(cal); } else { break; } } return(count); }
/// <summary> /// Store and schedule the identified <see cref="IOperableTrigger"/> /// </summary> /// <param name="trig"></param> public void TriggerJob(IOperableTrigger trig) { ValidateState(); trig.ComputeFirstFireTimeUtc(null); bool collision = true; while (collision) { try { resources.JobStore.StoreTrigger(trig, false); collision = false; } catch (ObjectAlreadyExistsException) { trig.Key = new TriggerKey(NewTriggerId(), SchedulerConstants.DefaultGroup); } } NotifySchedulerThread(trig.GetNextFireTimeUtc()); NotifySchedulerListenersScheduled(trig); }