[Platform(Exclude = "Linux")] // TODO seems that we have some trouble on Linux with this public async Task ReschedulingTriggerShouldKeepOriginalNextFireTime() { NameValueCollection properties = new NameValueCollection(); properties["quartz.serializer.type"] = TestConstants.DefaultSerializerType; ISchedulerFactory factory = new StdSchedulerFactory(properties); IScheduler scheduler = await factory.GetScheduler(); await scheduler.Start(); var job = JobBuilder.Create <NoOpJob>().Build(); IOperableTrigger trigger = (IOperableTrigger)TriggerBuilder.Create() .WithSimpleSchedule(x => x.WithIntervalInHours(1).RepeatForever()) .ForJob(job) .StartNow() .Build(); await scheduler.ScheduleJob(job, trigger); trigger = (IOperableTrigger)await scheduler.GetTrigger(trigger.Key); Assert.That(trigger.GetPreviousFireTimeUtc(), Is.EqualTo(null)); var previousFireTimeUtc = DateTimeOffset.UtcNow.AddDays(1); trigger.SetPreviousFireTimeUtc(previousFireTimeUtc); trigger.SetNextFireTimeUtc(trigger.GetFireTimeAfter(previousFireTimeUtc)); await scheduler.RescheduleJob(trigger.Key, trigger); trigger = (IOperableTrigger)await scheduler.GetTrigger(trigger.Key); Assert.That(trigger.GetNextFireTimeUtc().Value.UtcDateTime, Is.EqualTo(previousFireTimeUtc.AddHours(1).UtcDateTime).Within(TimeSpan.FromSeconds(5))); await scheduler.Shutdown(true); }
public Trigger(IOperableTrigger newTrigger, string schedulerInstanceName) { if (newTrigger == null) { return; } Name = newTrigger.Key.Name; Group = newTrigger.Key.Group; JobName = newTrigger.JobKey.Name; JobKey = $"{JobName}/{newTrigger.JobKey.Group}"; Scheduler = schedulerInstanceName; State = InternalTriggerState.Waiting; Description = newTrigger.Description; CalendarName = newTrigger.CalendarName; JobDataMap = newTrigger.JobDataMap.WrappedMap; FinalFireTimeUtc = newTrigger.FinalFireTimeUtc; MisfireInstruction = newTrigger.MisfireInstruction; Priority = newTrigger.Priority; HasMillisecondPrecision = newTrigger.HasMillisecondPrecision; FireInstanceId = newTrigger.FireInstanceId; EndTimeUtc = newTrigger.EndTimeUtc; StartTimeUtc = newTrigger.StartTimeUtc; NextFireTimeUtc = newTrigger.GetNextFireTimeUtc(); PreviousFireTimeUtc = newTrigger.GetPreviousFireTimeUtc(); if (NextFireTimeUtc != null) { NextFireTimeTicks = NextFireTimeUtc.Value.UtcTicks; } // Init trigger specific properties according to type of newTrigger. // If an option doesn't apply to the type of trigger it will stay null by default. switch (newTrigger) { case CronTriggerImpl cronTriggerImpl: Cron = new CronOptions { CronExpression = cronTriggerImpl.CronExpressionString, TimeZoneId = cronTriggerImpl.TimeZone.Id }; return; case SimpleTriggerImpl simpTriggerImpl: Simp = new SimpleOptions { RepeatCount = simpTriggerImpl.RepeatCount, RepeatInterval = simpTriggerImpl.RepeatInterval }; return; case CalendarIntervalTriggerImpl calTriggerImpl: Cal = new CalendarOptions { RepeatIntervalUnit = calTriggerImpl.RepeatIntervalUnit, RepeatInterval = calTriggerImpl.RepeatInterval, TimesTriggered = calTriggerImpl.TimesTriggered, TimeZoneId = calTriggerImpl.TimeZone.Id, PreserveHourOfDayAcrossDaylightSavings = calTriggerImpl.PreserveHourOfDayAcrossDaylightSavings, SkipDayIfHourDoesNotExist = calTriggerImpl.SkipDayIfHourDoesNotExist }; return; case DailyTimeIntervalTriggerImpl dayTriggerImpl: Day = new DailyTimeOptions { RepeatCount = dayTriggerImpl.RepeatCount, RepeatIntervalUnit = dayTriggerImpl.RepeatIntervalUnit, RepeatInterval = dayTriggerImpl.RepeatInterval, StartTimeOfDay = dayTriggerImpl.StartTimeOfDay, EndTimeOfDay = dayTriggerImpl.EndTimeOfDay, DaysOfWeek = dayTriggerImpl.DaysOfWeek, TimesTriggered = dayTriggerImpl.TimesTriggered, TimeZoneId = dayTriggerImpl.TimeZone.Id }; break; } }
protected virtual TriggerFiredBundle TriggerFired(ConnectionAndTransactionHolder conn, IOperableTrigger trigger) { IJobDetail job; ICalendar cal = null; // Make sure trigger wasn't deleted, paused, or completed... try { // if trigger was deleted, state will be StateDeleted string state = Delegate.SelectTriggerState(conn, trigger.Key); if (!state.Equals(StateAcquired)) { return null; } } catch (Exception e) { throw new JobPersistenceException("Couldn't select trigger state: " + e.Message, e); } try { job = RetrieveJob(conn, trigger.JobKey); if (job == null) { return null; } } catch (JobPersistenceException jpe) { try { Log.Error("Error retrieving job, setting trigger state to ERROR.", jpe); Delegate.UpdateTriggerState(conn, trigger.Key, StateError); } catch (Exception sqle) { Log.Error("Unable to set trigger state to ERROR.", sqle); } throw; } if (trigger.CalendarName != null) { cal = RetrieveCalendar(conn, trigger.CalendarName); if (cal == null) { return null; } } try { Delegate.UpdateFiredTrigger(conn, trigger, StateExecuting, job); } catch (Exception e) { throw new JobPersistenceException("Couldn't insert fired trigger: " + e.Message, e); } DateTimeOffset? prevFireTime = trigger.GetPreviousFireTimeUtc(); // call triggered - to update the trigger's next-fire-time state... trigger.Triggered(cal); string state2 = StateWaiting; bool force = true; if (job.ConcurrentExecutionDisallowed) { state2 = StateBlocked; force = false; try { Delegate.UpdateTriggerStatesForJobFromOtherState(conn, job.Key, StateBlocked, StateWaiting); Delegate.UpdateTriggerStatesForJobFromOtherState(conn, job.Key, StateBlocked, StateAcquired); Delegate.UpdateTriggerStatesForJobFromOtherState(conn, job.Key, StatePausedBlocked, StatePaused); } catch (Exception e) { throw new JobPersistenceException("Couldn't update states of blocked triggers: " + e.Message, e); } } if (!trigger.GetNextFireTimeUtc().HasValue) { state2 = StateComplete; force = true; } StoreTrigger(conn, trigger, job, true, state2, force, false); job.JobDataMap.ClearDirtyFlag(); return new TriggerFiredBundle( job, trigger, cal, trigger.Key.Group.Equals(SchedulerConstants.DefaultRecoveryGroup), SystemTime.UtcNow(), trigger.GetPreviousFireTimeUtc(), prevFireTime, trigger.GetNextFireTimeUtc()); }
internal static void PopulateBaseTriggerProperties(IOperableTrigger quartzTrigger, DbAbstractTrigger dbTrigger, string instanceName) { dbTrigger.CalendarName = quartzTrigger.CalendarName; dbTrigger.Description = quartzTrigger.Description; dbTrigger.JobGroup = quartzTrigger.JobKey.Group; dbTrigger.JobName = quartzTrigger.JobKey.Name; dbTrigger.MisfireInstruction = quartzTrigger.MisfireInstruction; dbTrigger.Priority = quartzTrigger.Priority; dbTrigger.Scheduler = instanceName; if (quartzTrigger.JobDataMap != null) { dbTrigger.JobData = new List<DbJobData>(); foreach (var jobDataItem in quartzTrigger.JobDataMap) { DbJobData dbJobData = new DbJobData(); dbJobData.Key = jobDataItem.Key; dbJobData.Value = jobDataItem.Value; dbJobData.Type = GetStorableJobTypeName(jobDataItem.Value.GetType()); dbTrigger.JobData.Add(dbJobData); } } dbTrigger.StartTime = new DateEpoch { Date = quartzTrigger.StartTimeUtc.UtcDateTime }; var endTime = quartzTrigger.EndTimeUtc; if (endTime.HasValue) dbTrigger.EndTime = new DateEpoch { Date = endTime.Value.UtcDateTime }; var nextFireTime = quartzTrigger.GetNextFireTimeUtc(); if (nextFireTime.HasValue) dbTrigger.NextFireTime = new DateEpoch { Date = nextFireTime.Value.UtcDateTime }; var previousFireTime = quartzTrigger.GetPreviousFireTimeUtc(); if (previousFireTime.HasValue) dbTrigger.PreviousFireTime = new DateEpoch { Date = previousFireTime.Value.UtcDateTime }; }