Ejemplo n.º 1
0
        /// <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>
        /// <returns>List of java.util.Date objects</returns>
        public static IList<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 Initialize()
 {
     _job = CreateJob();
     _trigger1 = CreateTrigger("trigger1", "triggerGroup1", _job.Key);
     _trigger2 = CreateTrigger("trigger2", "triggerGroup1", _job.Key);
     JobStore.StoreJob(_job, false);
     JobStore.StoreTrigger(_trigger1, false);
     JobStore.StoreTrigger(_trigger2, false);
 }
        protected override SimplePropertiesTriggerProperties GetTriggerProperties(IOperableTrigger trigger)
        {
            CalendarIntervalTriggerImpl calTrig = (CalendarIntervalTriggerImpl) trigger;

            SimplePropertiesTriggerProperties props = new SimplePropertiesTriggerProperties();

            props.Int1 = (calTrig.RepeatInterval);
            props.String1 = (calTrig.RepeatIntervalUnit.ToString());
            props.Int2 = (calTrig.TimesTriggered);

            return props;
        }
        public int InsertExtendedTriggerProperties(ConnectionAndTransactionHolder conn, IOperableTrigger trigger, string state, IJobDetail jobDetail)
        {
            ICronTrigger cronTrigger = (ICronTrigger) trigger;

            using (IDbCommand cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlInsertCronTrigger, TablePrefix, SchedNameLiteral)))
            {
                DbAccessor.AddCommandParameter(cmd, "triggerName", trigger.Key.Name);
                DbAccessor.AddCommandParameter(cmd, "triggerGroup", trigger.Key.Group);
                DbAccessor.AddCommandParameter(cmd, "triggerCronExpression", cronTrigger.CronExpressionString);
                DbAccessor.AddCommandParameter(cmd, "triggerTimeZone", cronTrigger.TimeZone.Id);

                return cmd.ExecuteNonQuery();
            }
        }
        public int InsertExtendedTriggerProperties(ConnectionAndTransactionHolder conn, IOperableTrigger trigger, string state, IJobDetail jobDetail)
        {
            ISimpleTrigger simpleTrigger = (ISimpleTrigger) trigger;

            using (IDbCommand cmd = commandAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlInsertSimpleTrigger, tablePrefix, schedNameLiteral)))
            {
                commandAccessor.AddCommandParameter(cmd, "triggerName", trigger.Key.Name);
                commandAccessor.AddCommandParameter(cmd, "triggerGroup", trigger.Key.Group);
                commandAccessor.AddCommandParameter(cmd, "triggerRepeatCount", simpleTrigger.RepeatCount);
                commandAccessor.AddCommandParameter(cmd, "triggerRepeatInterval", simpleTrigger.RepeatInterval.TotalMilliseconds);
                commandAccessor.AddCommandParameter(cmd, "triggerTimesTriggered", simpleTrigger.TimesTriggered);

                return cmd.ExecuteNonQuery();
            }
        }
        protected override SimplePropertiesTriggerProperties GetTriggerProperties(IOperableTrigger trigger)
        {
            CalendarIntervalTriggerImpl calTrig = (CalendarIntervalTriggerImpl) trigger;

            SimplePropertiesTriggerProperties props = new SimplePropertiesTriggerProperties();

            props.Int1 = calTrig.RepeatInterval;
            props.String1 = calTrig.RepeatIntervalUnit.ToString();
            props.Int2 = calTrig.TimesTriggered;
            props.String2 = calTrig.TimeZone.Id;
            props.Boolean1 = calTrig.PreserveHourOfDayAcrossDaylightSavings;
            props.Boolean2 = calTrig.SkipDayIfHourDoesNotExist;

            return props;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="TriggerFiredBundle"/> class.
 /// </summary>
 /// <param name="job">The job.</param>
 /// <param name="trigger">The trigger.</param>
 /// <param name="cal">The calendar.</param>
 /// <param name="jobIsRecovering">if set to <c>true</c> [job is recovering].</param>
 /// <param name="fireTimeUtc">The fire time.</param>
 /// <param name="scheduledFireTimeUtc">The scheduled fire time.</param>
 /// <param name="prevFireTimeUtc">The previous fire time.</param>
 /// <param name="nextFireTimeUtc">The next fire time.</param>
 public TriggerFiredBundle(IJobDetail job, IOperableTrigger trigger, ICalendar cal, bool jobIsRecovering,
     DateTimeOffset? fireTimeUtc,
     DateTimeOffset? scheduledFireTimeUtc,
     DateTimeOffset? prevFireTimeUtc,
     DateTimeOffset? nextFireTimeUtc)
 {
     this.job = job;
     this.trigger = trigger;
     this.cal = cal;
     this.jobIsRecovering = jobIsRecovering;
     this.fireTimeUtc = fireTimeUtc;
     this.scheduledFireTimeUtc = scheduledFireTimeUtc;
     this.prevFireTimeUtc = prevFireTimeUtc;
     this.nextFireTimeUtc = nextFireTimeUtc;
 }
Ejemplo n.º 8
0
        public async Task TestAcquireTriggers()
        {
            ISchedulerSignaler schedSignaler = new SampleSignaler();
            ITypeLoadHelper    loadHelper    = new SimpleTypeLoadHelper();

            loadHelper.Initialize();

            RAMJobStore store = new RAMJobStore();
            await store.Initialize(loadHelper, schedSignaler);

            // 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("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);

                await 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;
                var            triggers    = await store.AcquireNextTriggers(noLaterThan, maxCount, timeWindow);

                Assert.AreEqual(1, triggers.Count);
                Assert.AreEqual("job" + i, triggers[0].Key.Name);

                // Let's remove the trigger now.
                await store.RemoveJob(triggers[0].JobKey);
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Releases the trigger retry loop.
        /// </summary>
        /// <param name="trigger">The trigger.</param>
        public virtual void ReleaseTriggerRetryLoop(IOperableTrigger trigger)
        {
            int retryCount = 0;

            try
            {
                while (!halted)
                {
                    try
                    {
                        Thread.Sleep(DbFailureRetryInterval);
                        // retry every N seconds (the db connection must be failed)
                        retryCount++;
                        qsRsrcs.JobStore.ReleaseAcquiredTrigger(trigger);
                        retryCount = 0;
                        break;
                    }
                    catch (JobPersistenceException jpe)
                    {
                        if (retryCount % 4 == 0)
                        {
                            qs.NotifySchedulerListenersError(
                                string.Format(CultureInfo.InvariantCulture, "An error occurred while releasing trigger '{0}'", trigger.Key), jpe);
                        }
                    }
                    catch (ThreadInterruptedException e)
                    {
                        Log.Error(string.Format(CultureInfo.InvariantCulture, "ReleaseTriggerRetryLoop: InterruptedException {0}", e.Message), e);
                    }
                    catch (Exception e)
                    {
                        Log.Error(string.Format(CultureInfo.InvariantCulture, "ReleaseTriggerRetryLoop: Exception {0}", e.Message), e);
                    }
                }
            }
            finally
            {
                if (retryCount == 0)
                {
                    Log.Info("ReleaseTriggerRetryLoop: connection restored.");
                }
            }
        }
Ejemplo n.º 10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TriggerFiredBundle"/> class.
 /// </summary>
 /// <param name="job">The job.</param>
 /// <param name="trigger">The trigger.</param>
 /// <param name="cal">The calendar.</param>
 /// <param name="jobIsRecovering">if set to <c>true</c> [job is recovering].</param>
 /// <param name="fireTimeUtc">The fire time.</param>
 /// <param name="scheduledFireTimeUtc">The scheduled fire time.</param>
 /// <param name="prevFireTimeUtc">The previous fire time.</param>
 /// <param name="nextFireTimeUtc">The next fire time.</param>
 public TriggerFiredBundle(
     IJobDetail job,
     IOperableTrigger trigger,
     ICalendar cal,
     bool jobIsRecovering,
     DateTimeOffset fireTimeUtc,
     DateTimeOffset?scheduledFireTimeUtc,
     DateTimeOffset?prevFireTimeUtc,
     DateTimeOffset?nextFireTimeUtc)
 {
     JobDetail            = job;
     Trigger              = trigger;
     Calendar             = cal;
     Recovering           = jobIsRecovering;
     FireTimeUtc          = fireTimeUtc;
     ScheduledFireTimeUtc = scheduledFireTimeUtc;
     PrevFireTimeUtc      = prevFireTimeUtc;
     NextFireTimeUtc      = nextFireTimeUtc;
 }
Ejemplo n.º 11
0
        public async Task <int> InsertExtendedTriggerProperties(
            ConnectionAndTransactionHolder conn,
            IOperableTrigger trigger,
            string state,
            IJobDetail jobDetail,
            CancellationToken cancellationToken = default)
        {
            ISimpleTrigger simpleTrigger = (ISimpleTrigger)trigger;

            using (var cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlInsertSimpleTrigger, TablePrefix, SchedNameLiteral)))
            {
                DbAccessor.AddCommandParameter(cmd, "triggerName", trigger.Key.Name);
                DbAccessor.AddCommandParameter(cmd, "triggerGroup", trigger.Key.Group);
                DbAccessor.AddCommandParameter(cmd, "triggerRepeatCount", simpleTrigger.RepeatCount);
                DbAccessor.AddCommandParameter(cmd, "triggerRepeatInterval", DbAccessor.GetDbTimeSpanValue(simpleTrigger.RepeatInterval));
                DbAccessor.AddCommandParameter(cmd, "triggerTimesTriggered", simpleTrigger.TimesTriggered);

                return(await cmd.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false));
            }
        }
Ejemplo n.º 12
0
        public async Task <int> InsertExtendedTriggerProperties(
            ConnectionAndTransactionHolder conn,
            IOperableTrigger trigger,
            string state,
            IJobDetail jobDetail,
            CancellationToken cancellationToken = default)
        {
            ICronTrigger cronTrigger = (ICronTrigger)trigger;

            using (var cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlInsertCronTrigger, TablePrefix)))
            {
                DbAccessor.AddCommandParameter(cmd, "schedulerName", SchedName);
                DbAccessor.AddCommandParameter(cmd, "triggerName", trigger.Key.Name);
                DbAccessor.AddCommandParameter(cmd, "triggerGroup", trigger.Key.Group);
                DbAccessor.AddCommandParameter(cmd, "triggerCronExpression", cronTrigger.CronExpressionString);
                DbAccessor.AddCommandParameter(cmd, "triggerTimeZone", cronTrigger.TimeZone.Id);

                return(await cmd.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false));
            }
        }
Ejemplo n.º 13
0
        public void TestAcquireTriggersInBatch()
        {
            ISchedulerSignaler schedSignaler = new SampleSignaler();
            ITypeLoadHelper    loadHelper    = new SimpleTypeLoadHelper();

            loadHelper.Initialize();

            var store = new RavenJobStore();

            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("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 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("trigger" + i, triggers[i].Key.Name);
            }
        }
        protected override SimplePropertiesTriggerProperties GetTriggerProperties(IOperableTrigger trigger)
        {
            DailyTimeIntervalTriggerImpl dailyTrigger = (DailyTimeIntervalTriggerImpl) trigger;
            SimplePropertiesTriggerProperties props = new SimplePropertiesTriggerProperties();

            props.Int1 = dailyTrigger.RepeatInterval;
            props.String1 = dailyTrigger.RepeatIntervalUnit.ToString();
            props.Int2 = dailyTrigger.TimesTriggered;

            ISet<DayOfWeek> days = dailyTrigger.DaysOfWeek;
            string daysStr = string.Join(",", days.Cast<int>().Select(x => x.ToString(CultureInfo.InvariantCulture)).ToArray());
            props.String2 = daysStr;

            StringBuilder timeOfDayBuffer = new StringBuilder();
            TimeOfDay startTimeOfDay = dailyTrigger.StartTimeOfDay;
            if (startTimeOfDay != null)
            {
                timeOfDayBuffer.Append(startTimeOfDay.Hour).Append(",");
                timeOfDayBuffer.Append(startTimeOfDay.Minute).Append(",");
                timeOfDayBuffer.Append(startTimeOfDay.Second).Append(",");
            }
            else
            {
                timeOfDayBuffer.Append(",,,");
            }

            TimeOfDay endTimeOfDay = dailyTrigger.EndTimeOfDay;
            if (endTimeOfDay != null)
            {
                timeOfDayBuffer.Append(endTimeOfDay.Hour).Append(",");
                timeOfDayBuffer.Append(endTimeOfDay.Minute).Append(",");
                timeOfDayBuffer.Append(endTimeOfDay.Second);
            }
            else
            {
                timeOfDayBuffer.Append(",,,");
            }
            props.String3 = timeOfDayBuffer.ToString();
            props.Long1 = dailyTrigger.RepeatCount;
            return props;
        }
Ejemplo n.º 15
0
 /// <summary>
 /// Vetoeds the job retry loop.
 /// </summary>
 /// <param name="trigger">The trigger.</param>
 /// <param name="jobDetail">The job detail.</param>
 /// <param name="instCode">The inst code.</param>
 /// <returns></returns>
 public bool VetoedJobRetryLoop(IOperableTrigger trigger, IJobDetail jobDetail, SchedulerInstruction instCode)
 {
     while (!shutdownRequested)
     {
         try
         {
             Thread.Sleep(qs.DbRetryInterval); // retry per config setting (the db connection must be failed)
             qs.NotifyJobStoreJobVetoed(trigger, jobDetail, instCode);
             return(true);
         }
         catch (JobPersistenceException jpe)
         {
             qs.NotifySchedulerListenersError(
                 string.Format(CultureInfo.InvariantCulture, "An error occured while marking executed job vetoed. job= '{0}'", jobDetail.Key), jpe);
         }
         catch (ThreadInterruptedException)
         {
         }
     }
     return(false);
 }
Ejemplo n.º 16
0
        /// <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);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Compute the <see cref="DateTimeOffset" /> that is 1 second after the Nth firing of 
        /// the given <see cref="ITrigger" />, taking the triger'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;
        }
Ejemplo n.º 18
0
        /// <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());
        }
Ejemplo n.º 19
0
        // 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);
        }
Ejemplo n.º 20
0
        static IOperableTrigger CreateTriggerCore(this IXpandJobTrigger jobTrigger, Type jobType)
        {
            IOperableTrigger trigger = null;

            if (jobTrigger is IXpandSimpleTrigger)
            {
                trigger = new SimpleTriggerImpl(jobTrigger.Name, jobType.FullName);
            }
            if (jobTrigger is IXpandCronTrigger)
            {
                trigger = new CronTriggerImpl(jobTrigger.Name, jobType.FullName);
            }
            if (jobTrigger is INthIncludedDayTrigger)
            {
                trigger = new NthIncludedDayTrigger(jobTrigger.Name, jobType.FullName);
            }

            if (trigger != null)
            {
                return(trigger);
            }
            throw new NotImplementedException(jobTrigger.GetType().FullName);
        }
Ejemplo n.º 21
0
 public static void AssignQuartzTrigger(this IOperableTrigger jobTrigger, IXpandJobTrigger trigger, string jobName, Type type, string jobGroup)
 {
     jobTrigger.EndTimeUtc   = trigger.EndTimeUtc;
     jobTrigger.Priority     = (int)trigger.Priority;
     jobTrigger.CalendarName = GetCalendarName(trigger);
     jobTrigger.JobDataMap   = new JobDataMap();
     jobTrigger.StartTimeUtc = trigger.StartTimeUtc;
     jobTrigger.Description  = trigger.Description;
     jobTrigger.JobKey       = new JobKey(jobName, type.FullName);
     jobTrigger.Key          = new TriggerKey(jobTrigger.Key.Name, GetGroup(jobName, type, jobGroup));
     if (jobTrigger is SimpleTriggerImpl)
     {
         ((SimpleTriggerImpl)jobTrigger).AssignQuartzTrigger((IXpandSimpleTrigger)trigger);
     }
     else if (jobTrigger is CronTriggerImpl)
     {
         ((CronTriggerImpl)jobTrigger).AssignQuartzTrigger((IXpandCronTrigger)trigger);
     }
     else if (jobTrigger is NthIncludedDayTrigger)
     {
         ((NthIncludedDayTrigger)jobTrigger).AssignQuartzTrigger((INthIncludedDayTrigger)trigger);
     }
 }
Ejemplo n.º 22
0
        [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);
        }
Ejemplo n.º 23
0
        protected virtual bool ReplaceTrigger(ConnectionAndTransactionHolder conn,
                                             TriggerKey triggerKey, IOperableTrigger newTrigger)
        {
            try
            {
                // this must be called before we delete the trigger, obviously
                IJobDetail job = Delegate.SelectJobForTrigger(conn, triggerKey, TypeLoadHelper);

                if (job == null)
                {
                    return false;
                }

                if (!newTrigger.JobKey.Equals(job.Key))
                {
                    throw new JobPersistenceException("New trigger is not related to the same job as the old trigger.");
                }

                bool removedTrigger = DeleteTriggerAndChildren(conn, triggerKey);

                StoreTrigger(conn, newTrigger, job, false, StateWaiting, false, false);

                return removedTrigger;
            }
            catch (Exception e)
            {
                throw new JobPersistenceException("Couldn't remove trigger: " + e.Message, e);
            }
        }
Ejemplo n.º 24
0
 public void TriggeredJobComplete(IOperableTrigger trigger, IJobDetail jobDetail, SchedulerInstruction triggerInstCode)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 25
0
 public bool CanHandleTriggerType(IOperableTrigger trigger)
 {
     return((trigger is CronTriggerImpl) && !((CronTriggerImpl)trigger).HasAdditionalProperties);
 }
Ejemplo n.º 26
0
        /// <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>
        /// <returns>List of java.util.Date objects</returns>
        public static IList<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();
        }
Ejemplo n.º 27
0
 public static DateTimeOffset? RescheduleJob(this IScheduler scheduler, IOperableTrigger trigger) {
     return scheduler.RescheduleJob(trigger.Key, trigger);
 }
Ejemplo n.º 28
0
        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());
        }
Ejemplo n.º 29
0
 /// <summary>
 /// Inform the <see cref="IJobStore" /> that the scheduler no longer plans to
 /// fire the given <see cref="ITrigger" />, that it had previously acquired
 /// (reserved).
 /// </summary>
 public virtual void ReleaseAcquiredTrigger(IOperableTrigger trigger)
 {
     lock (lockObject)
     {
         this.Triggers.Update(
             Query.EQ("_id", trigger.Key.ToBsonDocument()),
             Update.Unset("SchedulerInstanceId")
                 .Set("State", "Waiting"));
     }
 }
Ejemplo n.º 30
0
 public void StoreTrigger(IOperableTrigger newTrigger, bool replaceExisting)
 {
     throw new NotImplementedException();
 }
        public override bool CanHandleTriggerType(IOperableTrigger trigger)
        {
            var calendarIntervalTriggerImpl = trigger as CalendarIntervalTriggerImpl;

            return(calendarIntervalTriggerImpl != null && !calendarIntervalTriggerImpl.HasAdditionalProperties);
        }
Ejemplo n.º 32
0
 public bool ReplaceTrigger(TriggerKey triggerKey, IOperableTrigger newTrigger)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 33
0
        public int InsertExtendedTriggerProperties(ConnectionAndTransactionHolder conn, IOperableTrigger trigger, string state, IJobDetail jobDetail)
        {
            ISimpleTrigger simpleTrigger = (ISimpleTrigger)trigger;

            using (IDbCommand cmd = commandAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlInsertSimpleTrigger, tablePrefix, schedNameLiteral)))
            {
                commandAccessor.AddCommandParameter(cmd, "triggerName", trigger.Key.Name);
                commandAccessor.AddCommandParameter(cmd, "triggerGroup", trigger.Key.Group);
                commandAccessor.AddCommandParameter(cmd, "triggerRepeatCount", simpleTrigger.RepeatCount);
                commandAccessor.AddCommandParameter(cmd, "triggerRepeatInterval", simpleTrigger.RepeatInterval.TotalMilliseconds);
                commandAccessor.AddCommandParameter(cmd, "triggerTimesTriggered", simpleTrigger.TimesTriggered);

                return(cmd.ExecuteNonQuery());
            }
        }
Ejemplo n.º 34
0
 public void ReleaseAcquiredTrigger(IOperableTrigger trigger)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 35
0
        /// <summary>
        /// This method has to be implemented in order that starting of the thread causes the object's
        /// run method to be called in that separately executing thread.
        /// </summary>
        public virtual void Run()
        {
            qs.AddInternalSchedulerListener(this);

            try
            {
                IOperableTrigger trigger   = (IOperableTrigger)jec.Trigger;
                IJobDetail       jobDetail = jec.JobDetail;
                do
                {
                    JobExecutionException jobExEx = null;
                    IJob job = jec.JobInstance;

                    try
                    {
                        Begin();
                    }
                    catch (SchedulerException se)
                    {
                        qs.NotifySchedulerListenersError(
                            string.Format(CultureInfo.InvariantCulture, "Error executing Job ({0}: couldn't begin execution.", jec.JobDetail.Key),
                            se);
                        break;
                    }

                    // notify job & trigger listeners...
                    SchedulerInstruction instCode;
                    try
                    {
                        if (!NotifyListenersBeginning(jec))
                        {
                            break;
                        }
                    }
                    catch (VetoedException)
                    {
                        try
                        {
                            instCode = trigger.ExecutionComplete(jec, null);
                            try
                            {
                                qs.NotifyJobStoreJobVetoed(trigger, jobDetail, instCode);
                            }
                            catch (JobPersistenceException)
                            {
                                VetoedJobRetryLoop(trigger, jobDetail, instCode);
                            }

                            // Even if trigger got vetoed, we still needs to check to see if it's the trigger's finalized run or not.
                            if (jec.Trigger.GetNextFireTimeUtc() == null)
                            {
                                qs.NotifySchedulerListenersFinalized(jec.Trigger);
                            }
                            Complete(true);
                        }
                        catch (SchedulerException se)
                        {
                            qs.NotifySchedulerListenersError(
                                string.Format(CultureInfo.InvariantCulture, "Error during veto of Job ({0}: couldn't finalize execution.",
                                              jec.JobDetail.Key), se);
                        }
                        break;
                    }

                    DateTimeOffset startTime = SystemTime.UtcNow();
                    DateTimeOffset endTime;

                    // Execute the job
                    try
                    {
                        if (log.IsDebugEnabled)
                        {
                            log.Debug("Calling Execute on job " + jobDetail.Key);
                        }
                        job.Execute(jec);
                        endTime = SystemTime.UtcNow();
                    }
                    catch (JobExecutionException jee)
                    {
                        endTime = SystemTime.UtcNow();
                        jobExEx = jee;
                        log.Info(string.Format(CultureInfo.InvariantCulture, "Job {0} threw a JobExecutionException: ", jobDetail.Key), jobExEx);
                    }
                    catch (Exception e)
                    {
                        endTime = SystemTime.UtcNow();
                        log.Error(string.Format(CultureInfo.InvariantCulture, "Job {0} threw an unhandled Exception: ", jobDetail.Key), e);
                        SchedulerException se = new SchedulerException("Job threw an unhandled exception.", e);
                        qs.NotifySchedulerListenersError(
                            string.Format(CultureInfo.InvariantCulture, "Job ({0} threw an exception.", jec.JobDetail.Key), se);
                        jobExEx = new JobExecutionException(se, false);
                    }

                    jec.JobRunTime = endTime - startTime;

                    // notify all job listeners
                    if (!NotifyJobListenersComplete(jec, jobExEx))
                    {
                        break;
                    }

                    instCode = SchedulerInstruction.NoInstruction;

                    // update the trigger
                    try
                    {
                        instCode = trigger.ExecutionComplete(jec, jobExEx);
                        if (log.IsDebugEnabled)
                        {
                            log.Debug(string.Format(CultureInfo.InvariantCulture, "Trigger instruction : {0}", instCode));
                        }
                    }
                    catch (Exception e)
                    {
                        // If this happens, there's a bug in the trigger...
                        SchedulerException se = new SchedulerException("Trigger threw an unhandled exception.", e);
                        qs.NotifySchedulerListenersError("Please report this error to the Quartz developers.", se);
                    }

                    // notify all trigger listeners
                    if (!NotifyTriggerListenersComplete(jec, instCode))
                    {
                        break;
                    }
                    // update job/trigger or re-Execute job
                    if (instCode == SchedulerInstruction.ReExecuteJob)
                    {
                        if (log.IsDebugEnabled)
                        {
                            log.Debug("Rescheduling trigger to reexecute");
                        }
                        jec.IncrementRefireCount();
                        try
                        {
                            Complete(false);
                        }
                        catch (SchedulerException se)
                        {
                            qs.NotifySchedulerListenersError(
                                string.Format(CultureInfo.InvariantCulture, "Error executing Job ({0}: couldn't finalize execution.",
                                              jec.JobDetail.Key), se);
                        }
                        continue;
                    }

                    try
                    {
                        Complete(true);
                    }
                    catch (SchedulerException se)
                    {
                        qs.NotifySchedulerListenersError(
                            string.Format(CultureInfo.InvariantCulture, "Error executing Job ({0}: couldn't finalize execution.",
                                          jec.JobDetail.Key), se);
                        continue;
                    }

                    try
                    {
                        qs.NotifyJobStoreJobComplete(trigger, jobDetail, instCode);
                    }
                    catch (JobPersistenceException jpe)
                    {
                        qs.NotifySchedulerListenersError(
                            string.Format(CultureInfo.InvariantCulture, "An error occured while marking executed job complete. job= '{0}'",
                                          jobDetail.Key), jpe);
                        if (!CompleteTriggerRetryLoop(trigger, jobDetail, instCode))
                        {
                            return;
                        }
                    }

                    break;
                } while (true);
            }
            finally
            {
                qs.RemoveInternalSchedulerListener(this);
                if (jec != null && jec.JobInstance != null)
                {
                    qs.JobFactory.ReturnJob(jec.JobInstance);
                }
            }
        }
Ejemplo n.º 36
0
        /// <summary>
        /// Insert or update a trigger.
        /// </summary>
        protected virtual void StoreTrigger(ConnectionAndTransactionHolder conn, IOperableTrigger newTrigger, IJobDetail job, bool replaceExisting, string state, bool forceState, bool recovering)
        {
            bool existingTrigger = TriggerExists(conn, newTrigger.Key);

            if ((existingTrigger) && (!replaceExisting))
            {
                throw new ObjectAlreadyExistsException(newTrigger);
            }

            try
            {
                if (!forceState)
                {
                    bool shouldBepaused = Delegate.IsTriggerGroupPaused(conn, newTrigger.Key.Group);

                    if (!shouldBepaused)
                    {
                        shouldBepaused = Delegate.IsTriggerGroupPaused(conn, AllGroupsPaused);

                        if (shouldBepaused)
                        {
                            Delegate.InsertPausedTriggerGroup(conn, newTrigger.Key.Group);
                        }
                    }

                    if (shouldBepaused &&
                        (state.Equals(StateWaiting) || state.Equals(StateAcquired)))
                    {
                        state = StatePaused;
                    }
                }

                if (job == null)
                {
                    job = Delegate.SelectJobDetail(conn, newTrigger.JobKey, TypeLoadHelper);
                }
                if (job == null)
                {
                    throw new JobPersistenceException("The job (" + newTrigger.JobKey +
                                                      ") referenced by the trigger does not exist.");
                }
                if (job.ConcurrentExecutionDisallowed && !recovering)
                {
                    state = CheckBlockedState(conn, job.Key, state);
                }
                if (existingTrigger)
                {
                    Delegate.UpdateTrigger(conn, newTrigger, state, job);
                }
                else
                {
                    Delegate.InsertTrigger(conn, newTrigger, state, job);
                }
            }
            catch (Exception e)
            {
                string message = String.Format("Couldn't store trigger '{0}' for '{1}' job: {2}", newTrigger.Key, newTrigger.JobKey, e.Message);
                throw new JobPersistenceException(message, e);
            }
        }
Ejemplo n.º 37
0
        protected virtual void TriggeredJobComplete(ConnectionAndTransactionHolder conn,
                                                    IOperableTrigger trigger,
                                                    IJobDetail jobDetail, SchedulerInstruction triggerInstCode)
        {
            try
            {
                if (triggerInstCode == SchedulerInstruction.DeleteTrigger)
                {
                    if (!trigger.GetNextFireTimeUtc().HasValue)
                    {
                        // double check for possible reschedule within job
                        // execution, which would cancel the need to delete...
                        TriggerStatus stat = Delegate.SelectTriggerStatus(conn, trigger.Key);
                        if (stat != null && !stat.NextFireTimeUtc.HasValue)
                        {
                            RemoveTrigger(conn, trigger.Key);
                        }
                    }
                    else
                    {
                        RemoveTrigger(conn, trigger.Key);
                        SignalSchedulingChangeOnTxCompletion(null);
                    }
                }
                else if (triggerInstCode == SchedulerInstruction.SetTriggerComplete)
                {
                    Delegate.UpdateTriggerState(conn, trigger.Key, StateComplete);
                    SignalSchedulingChangeOnTxCompletion(null);
                }
                else if (triggerInstCode == SchedulerInstruction.SetTriggerError)
                {
                    Log.Info("Trigger " + trigger.Key + " set to ERROR state.");
                    Delegate.UpdateTriggerState(conn, trigger.Key, StateError);
                    SignalSchedulingChangeOnTxCompletion(null);
                }
                else if (triggerInstCode == SchedulerInstruction.SetAllJobTriggersComplete)
                {
                    Delegate.UpdateTriggerStatesForJob(conn, trigger.JobKey, StateComplete);
                    SignalSchedulingChangeOnTxCompletion(null);
                }
                else if (triggerInstCode == SchedulerInstruction.SetAllJobTriggersError)
                {
                    Log.Info("All triggers of Job " + trigger.JobKey + " set to ERROR state.");
                    Delegate.UpdateTriggerStatesForJob(conn, trigger.JobKey, StateError);
                    SignalSchedulingChangeOnTxCompletion(null);
                }

                if (jobDetail.ConcurrentExecutionDisallowed)
                {
                    Delegate.UpdateTriggerStatesForJobFromOtherState(conn, jobDetail.Key, StateWaiting, StateBlocked);
                    Delegate.UpdateTriggerStatesForJobFromOtherState(conn, jobDetail.Key, StatePaused, StatePausedBlocked);
                    SignalSchedulingChangeOnTxCompletion(null);
                }
                if (jobDetail.PersistJobDataAfterExecution)
                {
                    try
                    {
                        if (jobDetail.JobDataMap.Dirty)
                        {
                            Delegate.UpdateJobData(conn, jobDetail);
                        }
                    }
                    catch (IOException e)
                    {
                        throw new JobPersistenceException("Couldn't serialize job data: " + e.Message, e);
                    }
                    catch (Exception e)
                    {
                        throw new JobPersistenceException("Couldn't update job data: " + e.Message, e);
                    }
                }
            }
            catch (Exception e)
            {
                throw new JobPersistenceException("Couldn't update trigger state(s): " + e.Message, e);
            }

            try
            {
                Delegate.DeleteFiredTrigger(conn, trigger.FireInstanceId);
            }
            catch (Exception e)
            {
                throw new JobPersistenceException("Couldn't delete fired trigger: " + e.Message, e);
            }
        }
Ejemplo n.º 38
0
 protected internal void NotifyJobStoreJobVetoed(IOperableTrigger trigger, IJobDetail detail, SchedulerInstruction instCode)
 {
     resources.JobStore.TriggeredJobComplete(trigger, detail, instCode);
 }
Ejemplo n.º 39
0
        private void DoUpdateOfMisfiredTrigger(ConnectionAndTransactionHolder conn, IOperableTrigger trig,
                                               bool forceState, string newStateIfNotComplete, bool recovering)
        {
            ICalendar cal = null;
            if (trig.CalendarName != null)
            {
                cal = RetrieveCalendar(conn, trig.CalendarName);
            }

            schedSignaler.NotifyTriggerListenersMisfired(trig);

            trig.UpdateAfterMisfire(cal);

            if (!trig.GetNextFireTimeUtc().HasValue)
            {
                StoreTrigger(conn, trig, null, true, StateComplete, forceState, recovering);
                schedSignaler.NotifySchedulerListenersFinalized(trig);
            }
            else
            {
                StoreTrigger(conn, trig, null, true, newStateIfNotComplete, forceState, false);
            }
        }
 public override bool CanHandleTriggerType(IOperableTrigger trigger)
 {
     return((trigger is DailyTimeIntervalTriggerImpl) &&
            !((DailyTimeIntervalTriggerImpl)trigger).HasAdditionalProperties);
 }
Ejemplo n.º 41
0
 public static void StoreTrigger(this IScheduler scheduler, IOperableTrigger simpleTrigger) {
     scheduler.RescheduleJob(simpleTrigger.Key, simpleTrigger);
 }
        public int InsertExtendedTriggerProperties(ConnectionAndTransactionHolder conn, IOperableTrigger trigger, string state, IJobDetail jobDetail)
        {
            ICronTrigger cronTrigger = (ICronTrigger)trigger;

            using (IDbCommand cmd = DbAccessor.PrepareCommand(conn, AdoJobStoreUtil.ReplaceTablePrefix(StdAdoConstants.SqlInsertCronTrigger, TablePrefix, SchedNameLiteral)))
            {
                DbAccessor.AddCommandParameter(cmd, "triggerName", trigger.Key.Name);
                DbAccessor.AddCommandParameter(cmd, "triggerGroup", trigger.Key.Group);
                DbAccessor.AddCommandParameter(cmd, "triggerCronExpression", cronTrigger.CronExpressionString);
                DbAccessor.AddCommandParameter(cmd, "triggerTimeZone", cronTrigger.TimeZone.Id);

                return(cmd.ExecuteNonQuery());
            }
        }
Ejemplo n.º 43
0
        /// <summary>
        /// This method has to be implemented in order that starting of the thread causes the object's
        /// run method to be called in that separately executing thread.
        /// </summary>
        /// <param name="cancellationToken">The cancellation instruction.</param>
        public virtual async Task Run(CancellationToken cancellationToken = default)
        {
            Context.CallerId.Value = Guid.NewGuid();
            qs !.AddInternalSchedulerListener(this);

            try
            {
                IOperableTrigger trigger   = (IOperableTrigger)jec !.Trigger;
                IJobDetail       jobDetail = jec.JobDetail;
                do
                {
                    JobExecutionException?jobExEx = null;
                    IJob job = jec.JobInstance;

                    try
                    {
                        Begin();
                    }
                    catch (SchedulerException se)
                    {
                        string msg = $"Error executing Job {jec.JobDetail.Key}: couldn't begin execution.";
                        await qs.NotifySchedulerListenersError(msg, se, cancellationToken).ConfigureAwait(false);

                        break;
                    }

                    // notify job & trigger listeners...
                    SchedulerInstruction instCode;
                    try
                    {
                        if (!await NotifyListenersBeginning(jec, cancellationToken).ConfigureAwait(false))
                        {
                            break;
                        }
                    }
                    catch (VetoedException)
                    {
                        try
                        {
                            instCode = trigger.ExecutionComplete(jec, null);
                            await qs.NotifyJobStoreJobVetoed(trigger, jobDetail, instCode, cancellationToken).ConfigureAwait(false);

                            // Even if trigger got vetoed, we still needs to check to see if it's the trigger's finalized run or not.
                            if (jec.Trigger.GetNextFireTimeUtc() == null)
                            {
                                await qs.NotifySchedulerListenersFinalized(jec.Trigger, cancellationToken).ConfigureAwait(false);
                            }
                            Complete(true);
                        }
                        catch (SchedulerException se)
                        {
                            string msg = $"Error during veto of Job {jec.JobDetail.Key}: couldn't finalize execution.";
                            await qs.NotifySchedulerListenersError(msg, se, cancellationToken).ConfigureAwait(false);
                        }
                        break;
                    }

                    DateTimeOffset startTime = SystemTime.UtcNow();
                    DateTimeOffset endTime;

#if DIAGNOSTICS_SOURCE
                    Activity?activity = null;
#endif

                    // Execute the job
                    try
                    {
                        if (log.IsDebugEnabled())
                        {
                            log.Debug("Calling Execute on job " + jobDetail.Key);
                        }

#if DIAGNOSTICS_SOURCE
                        activity = jobExecutionJobDiagnostics.WriteStarted(jec, startTime);
#endif

                        await job.Execute(jec).ConfigureAwait(false);

                        endTime = SystemTime.UtcNow();
                    }
                    catch (OperationCanceledException)

                        // handle only scheduler-related cancellations
                        when(cancellationToken.IsCancellationRequested)
                        {
                            endTime = SystemTime.UtcNow();
                            log.InfoFormat($"Job {jobDetail.Key} was cancelled");
                        }
                    catch (JobExecutionException jee)
                    {
                        endTime = SystemTime.UtcNow();
                        jobExEx = jee;
#if DIAGNOSTICS_SOURCE
                        jobExecutionJobDiagnostics.WriteException(activity, jobExEx);
#endif
                        log.ErrorException($"Job {jobDetail.Key} threw a JobExecutionException: ", jobExEx);
                    }
                    catch (Exception e)
                    {
                        endTime = SystemTime.UtcNow();
                        log.ErrorException($"Job {jobDetail.Key} threw an unhandled Exception: ", e);
                        SchedulerException se  = new SchedulerException("Job threw an unhandled exception.", e);
                        string             msg = $"Job {jec.JobDetail.Key} threw an exception.";
                        await qs.NotifySchedulerListenersError(msg, se, cancellationToken).ConfigureAwait(false);

                        jobExEx = new JobExecutionException(se, false);
                    }

                    jec.JobRunTime = endTime - startTime;

#if DIAGNOSTICS_SOURCE
                    jobExecutionJobDiagnostics.WriteStopped(activity, endTime, jec);
#endif

                    // notify all job listeners
                    if (!await NotifyJobListenersComplete(jec, jobExEx, cancellationToken).ConfigureAwait(false))
                    {
                        break;
                    }

                    instCode = SchedulerInstruction.NoInstruction;

                    // update the trigger
                    try
                    {
                        instCode = trigger.ExecutionComplete(jec, jobExEx);
                        if (log.IsDebugEnabled())
                        {
                            log.Debug($"Trigger instruction : {instCode}");
                        }
                    }
                    catch (Exception e)
                    {
                        // If this happens, there's a bug in the trigger...
                        SchedulerException se = new SchedulerException("Trigger threw an unhandled exception.", e);
                        await qs.NotifySchedulerListenersError("Please report this error to the Quartz developers.", se, cancellationToken).ConfigureAwait(false);
                    }

                    // notify all trigger listeners
                    if (!await NotifyTriggerListenersComplete(jec, instCode, cancellationToken).ConfigureAwait(false))
                    {
                        break;
                    }
                    // update job/trigger or re-Execute job
                    if (instCode == SchedulerInstruction.ReExecuteJob)
                    {
                        if (log.IsDebugEnabled())
                        {
                            log.Debug("Rescheduling trigger to reexecute");
                        }
                        jec.IncrementRefireCount();
                        try
                        {
                            Complete(false);
                        }
                        catch (SchedulerException se)
                        {
                            await qs.NotifySchedulerListenersError($"Error executing Job {jec.JobDetail.Key}: couldn't finalize execution.", se, cancellationToken).ConfigureAwait(false);
                        }
                        continue;
                    }

                    try
                    {
                        Complete(true);
                    }
                    catch (SchedulerException se)
                    {
                        await qs.NotifySchedulerListenersError($"Error executing Job {jec.JobDetail.Key}: couldn't finalize execution.", se, cancellationToken).ConfigureAwait(false);

                        continue;
                    }

                    await qs.NotifyJobStoreJobComplete(trigger, jobDetail, instCode, cancellationToken).ConfigureAwait(false);

                    break;
                } while (true);
            }
            finally
            {
                qs.RemoveInternalSchedulerListener(this);
                if (jec != null)
                {
                    if (jec.JobInstance != null)
                    {
                        qs.JobFactory.ReturnJob(jec.JobInstance);
                    }

                    jec.Dispose();
                }
            }
        }
Ejemplo n.º 44
0
 /// <summary>
 /// Store the given <see cref="IJobDetail" /> and <see cref="ITrigger" />.
 /// </summary>
 /// <param name="newJob">The <see cref="IJobDetail" /> to be stored.</param>
 /// <param name="newTrigger">The <see cref="ITrigger" /> to be stored.</param>
 public virtual void StoreJobAndTrigger(IJobDetail newJob, IOperableTrigger newTrigger)
 {
     StoreJob(newJob, false);
     StoreTrigger(newTrigger, false);
 }
Ejemplo n.º 45
0
        /// <summary> 
        /// Inform the <see cref="IJobStore" /> that the scheduler has completed the
        /// firing of the given <see cref="ITrigger" /> (and the execution its
        /// associated <see cref="IJob" />), and that the <see cref="JobDataMap" />
        /// in the given <see cref="IJobDetail" /> should be updated if the <see cref="IJob" />
        /// is stateful.
        /// </summary>
        public virtual void TriggeredJobComplete(IOperableTrigger trigger, IJobDetail jobDetail,
            SchedulerInstruction triggerInstCode)
        {
            lock (lockObject)
            {
                this.ReleaseAcquiredTrigger(trigger);

                // It's possible that the job is null if:
                //   1- it was deleted during execution
                //   2- RAMJobStore is being used only for volatile jobs / triggers
                //      from the JDBC job store

                if (jobDetail.PersistJobDataAfterExecution)
                {
                    this.Jobs.Update(
                        Query.EQ("_id", jobDetail.Key.ToBsonDocument()),
                        Update.Set("JobDataMap", jobDetail.JobDataMap.ToBsonDocument()));
                }

                if (jobDetail.ConcurrentExecutionDisallowed)
                {
                    IList<Spi.IOperableTrigger> jobTriggers = this.GetTriggersForJob(jobDetail.Key);
                    IEnumerable<BsonDocument> triggerKeys = jobTriggers.Select(t => t.Key.ToBsonDocument());
                    this.Triggers.Update(
                        Query.And(
                            Query.In("_id", triggerKeys),
                            Query.EQ("State", "Blocked")),
                        Update.Set("State", "Waiting"));

                    this.Triggers.Update(
                        Query.And(
                            Query.In("_id", triggerKeys),
                            Query.EQ("State", "PausedAndBlocked")),
                        Update.Set("State", "Paused"));

                    signaler.SignalSchedulingChange(null);
                }

                // even if it was deleted, there may be cleanup to do
                this.BlockedJobs.Remove(
                    Query.EQ("_id", jobDetail.Key.ToBsonDocument()));

                // check for trigger deleted during execution...
                if (triggerInstCode == SchedulerInstruction.DeleteTrigger)
                {
                    log.Debug("Deleting trigger");
                    DateTimeOffset? d = trigger.GetNextFireTimeUtc();
                    if (!d.HasValue)
                    {
                        // double check for possible reschedule within job
                        // execution, which would cancel the need to delete...
                        d = trigger.GetNextFireTimeUtc();
                        if (!d.HasValue)
                        {
                            this.RemoveTrigger(trigger.Key);
                        }
                        else
                        {
                            log.Debug("Deleting cancelled - trigger still active");
                        }
                    }
                    else
                    {
                        this.RemoveTrigger(trigger.Key);
                        signaler.SignalSchedulingChange(null);
                    }
                }
                else if (triggerInstCode == SchedulerInstruction.SetTriggerComplete)
                {
                    this.Triggers.Update(
                        Query.EQ("_id", trigger.Key.ToBsonDocument()),
                        Update.Set("State", "Complete"));

                    signaler.SignalSchedulingChange(null);
                }
                else if (triggerInstCode == SchedulerInstruction.SetTriggerError)
                {
                    Log.Info(string.Format(CultureInfo.InvariantCulture, "Trigger {0} set to ERROR state.", trigger.Key));
                    this.Triggers.Update(
                        Query.EQ("_id", trigger.Key.ToBsonDocument()),
                        Update.Set("State", "Error"));

                    signaler.SignalSchedulingChange(null);
                }
                else if (triggerInstCode == SchedulerInstruction.SetAllJobTriggersError)
                {
                    Log.Info(string.Format(CultureInfo.InvariantCulture, "All triggers of Job {0} set to ERROR state.", trigger.JobKey));
                    IList<Spi.IOperableTrigger> jobTriggers = this.GetTriggersForJob(jobDetail.Key);
                    IEnumerable<BsonDocument> triggerKeys = jobTriggers.Select(t => t.Key.ToBsonDocument());
                    this.Triggers.Update(
                        Query.In("_id", triggerKeys),
                        Update.Set("State", "Error"));

                    signaler.SignalSchedulingChange(null);
                }
                else if (triggerInstCode == SchedulerInstruction.SetAllJobTriggersComplete)
                {
                    IList<Spi.IOperableTrigger> jobTriggers = this.GetTriggersForJob(jobDetail.Key);
                    IEnumerable<BsonDocument> triggerKeys = jobTriggers.Select(t => t.Key.ToBsonDocument());
                    this.Triggers.Update(
                        Query.In("_id", triggerKeys),
                        Update.Set("State", "Complete"));

                    signaler.SignalSchedulingChange(null);
                }
            }
        }
Ejemplo n.º 46
0
        public async Task TestSelectSimpleTriggerWithDeleteBeforeSelectExtendedProps()
        {
            var dbProvider  = A.Fake <IDbProvider>();
            var connection  = A.Fake <DbConnection>();
            var transaction = A.Fake <DbTransaction>();
            var command     = (DbCommand)A.Fake <StubCommand>();
            var dbMetadata  = new DbMetadata();

            A.CallTo(() => dbProvider.Metadata).Returns(dbMetadata);

            A.CallTo(() => dbProvider.CreateCommand()).Returns(command);

            var dataReader = A.Fake <DbDataReader>();

            A.CallTo(command).Where(x => x.Method.Name == "ExecuteDbDataReaderAsync")
            .WithReturnType <Task <DbDataReader> >()
            .Returns(Task.FromResult(dataReader));

            A.CallTo(command).Where(x => x.Method.Name == "get_DbParameterCollection")
            .WithReturnType <DbParameterCollection>()
            .Returns(new StubParameterCollection());

            A.CallTo(() => command.CommandText).Returns("");

            A.CallTo(command).Where(x => x.Method.Name == "CreateDbParameter")
            .WithReturnType <DbParameter>()
            .Returns(new SqlParameter());

            var persistenceDelegate = A.Fake <ITriggerPersistenceDelegate>();
            var exception           = new InvalidOperationException();

            A.CallTo(() => persistenceDelegate.LoadExtendedTriggerProperties(A <ConnectionAndTransactionHolder> .Ignored, A <TriggerKey> .Ignored)).Throws(exception);

            StdAdoDelegate adoDelegate = new TestStdAdoDelegate(persistenceDelegate);

            var delegateInitializationArgs = new DelegateInitializationArgs
            {
                TablePrefix    = "QRTZ_",
                InstanceId     = "TESTSCHED",
                InstanceName   = "INSTANCE",
                TypeLoadHelper = new SimpleTypeLoadHelper(),
                UseProperties  = false,
                InitString     = "",
                Logger         = LogProvider.GetLogger(GetType()),
                DbProvider     = dbProvider
            };

            adoDelegate.Initialize(delegateInitializationArgs);

            // First result set has results, second has none
            A.CallTo(() => dataReader.ReadAsync(CancellationToken.None)).Returns(true).Once();
            A.CallTo(() => dataReader[AdoConstants.ColumnTriggerType]).Returns(AdoConstants.TriggerTypeSimple);
            A.CallTo(() => dataReader[A <string> ._]).Returns("1");

            var conn = new ConnectionAndTransactionHolder(connection, transaction);
            IOperableTrigger trigger = await adoDelegate.SelectTrigger(conn, new TriggerKey("test"));

            Assert.That(trigger, Is.Null);

            A.CallTo(() => persistenceDelegate.LoadExtendedTriggerProperties(A <ConnectionAndTransactionHolder> .Ignored, A <TriggerKey> .Ignored)).MustHaveHappened();
        }
Ejemplo n.º 47
0
        /// <summary>
        /// Creates the minimal fired bundle with job detail that has
        /// given job type.
        /// </summary>
        /// <param name="jobType">Type of the job.</param>
        /// <param name="trigger">The trigger.</param>
        /// <returns>Minimal TriggerFiredBundle</returns>
        public static TriggerFiredBundle CreateMinimalFiredBundleWithTypedJobDetail(Type jobType, IOperableTrigger trigger)
        {
            JobDetailImpl      jd     = new JobDetailImpl("jobName", "jobGroup", jobType);
            TriggerFiredBundle bundle = new TriggerFiredBundle(jd, trigger, null, false, DateTimeOffset.UtcNow, null, null, null);

            return(bundle);
        }
Ejemplo n.º 48
0
 public void StoreJobAndTrigger(IJobDetail newJob, IOperableTrigger newTrigger)
 {
     throw new NotImplementedException();
 }
Ejemplo n.º 49
0
 /// <summary>
 /// Store the given <see cref="IJobDetail" /> and <see cref="IOperableTrigger" />.
 /// </summary>
 /// <param name="newJob">Job to be stored.</param>
 /// <param name="newTrigger">Trigger to be stored.</param>
 public void StoreJobAndTrigger(IJobDetail newJob, IOperableTrigger newTrigger)
 {
     ExecuteInLock((LockOnInsert) ? LockTriggerAccess : null, conn =>
                                                                  {
                                                                      StoreJob(conn, newJob, false);
                                                                      StoreTrigger(conn, newTrigger, newJob, false, StateWaiting, false, false);
                                                                      return null;
                                                                  });
 }
Ejemplo n.º 50
0
 /// <summary>
 /// Store the given <see cref="ITrigger" />.
 /// </summary>
 /// <param name="newTrigger">The <see cref="ITrigger" /> to be stored.</param>
 /// <param name="replaceExisting">
 /// If <see langword="true" />, any <see cref="ITrigger" /> existing in
 /// the <see cref="IJobStore" /> with the same name &amp; group should
 /// be over-written.
 /// </param>
 /// <exception cref="ObjectAlreadyExistsException">
 /// if a <see cref="ITrigger" /> with the same name/group already
 /// exists, and replaceExisting is set to false.
 /// </exception>
 public void StoreTrigger(IOperableTrigger newTrigger, bool replaceExisting)
 {
     ExecuteInLock(
         (LockOnInsert || replaceExisting) ? LockTriggerAccess : null,
         conn => StoreTrigger(conn, newTrigger, null, replaceExisting, StateWaiting, false, false));
 }
Ejemplo n.º 51
0
        /// <summary>
        /// Replaces the trigger.
        /// </summary>
        /// <param name="triggerKey">The <see cref="TriggerKey"/> of the <see cref="ITrigger" /> to be replaced.</param>
        /// <param name="newTrigger">The new trigger.</param>
        /// <returns></returns>
        public virtual bool ReplaceTrigger(TriggerKey triggerKey, IOperableTrigger newTrigger)
        {
            bool found;

            lock (lockObject)
            {
                IOperableTrigger oldTrigger = this.Triggers.FindOneByIdAs<IOperableTrigger>(triggerKey.ToBsonDocument());
                found = oldTrigger != null;

                if (found)
                {
                    if (!oldTrigger.JobKey.Equals(newTrigger.JobKey))
                    {
                        throw new JobPersistenceException("New trigger is not related to the same job as the old trigger.");
                    }

                    this.RemoveTrigger(triggerKey);

                    try
                    {
                        this.StoreTrigger(newTrigger, false);
                    }
                    catch (JobPersistenceException)
                    {
                        this.StoreTrigger(oldTrigger, false); // put previous trigger back...
                        throw;
                    }
                }
            }

            return found;
        }
Ejemplo n.º 52
0
 /// <summary>
 /// Inform the <see cref="IJobStore" /> that the scheduler has completed the
 /// firing of the given <see cref="ITrigger" /> (and the execution its
 /// associated <see cref="IJob" />), and that the <see cref="JobDataMap" />
 /// in the given <see cref="IJobDetail" /> should be updated if the <see cref="IJob" />
 /// is stateful.
 /// </summary>
 public virtual void TriggeredJobComplete(IOperableTrigger trigger, IJobDetail jobDetail,
                                          SchedulerInstruction triggerInstCode)
 {
     ExecuteInNonManagedTXLock(LockTriggerAccess, conn => TriggeredJobComplete(conn, trigger, jobDetail, triggerInstCode));
 }
Ejemplo n.º 53
0
        /// <summary>
        /// Store the given <see cref="ITrigger" />.
        /// </summary>
        /// <param name="newTrigger">The <see cref="ITrigger" /> to be stored.</param>
        /// <param name="replaceExisting">If <see langword="true" />, any <see cref="ITrigger" /> existing in
        /// the <see cref="IJobStore" /> with the same name and group should
        /// be over-written.</param>
        public virtual void StoreTrigger(IOperableTrigger newTrigger, bool replaceExisting)
        {
            lock (lockObject)
            {
                if (this.CheckExists(newTrigger.Key))
                {
                    if (!replaceExisting)
                    {
                        throw new ObjectAlreadyExistsException(newTrigger);
                    }

                    // don't delete orphaned job, this trigger has the job anyways
                    this.RemoveTrigger(newTrigger.Key, false);
                }

                if (this.RetrieveJob(newTrigger.JobKey) == null)
                {
                    throw new JobPersistenceException("The job (" + newTrigger.JobKey +
                                                      ") referenced by the trigger does not exist.");
                }

                var document = newTrigger.ToBsonDocument();
                string state = "Waiting";

                if (this.PausedTriggerGroups.FindOneByIdAs<BsonDocument>(newTrigger.Key.Group) != null
                    || this.PausedJobGroups.FindOneByIdAs<BsonDocument>(newTrigger.JobKey.Group) != null)
                {
                    state = "Paused";
                    if (this.BlockedJobs.FindOneByIdAs<BsonDocument>(newTrigger.JobKey.ToBsonDocument()) != null)
                    {
                        state = "PausedAndBlocked";
                    }
                }
                else if (this.BlockedJobs.FindOneByIdAs<BsonDocument>(newTrigger.JobKey.ToBsonDocument()) != null)
                {
                    state = "Blocked";
                }

                document.Add("State", state);
                this.Triggers.Save(document);
            }
        }
Ejemplo n.º 54
0
 protected virtual void ReleaseAcquiredTrigger(ConnectionAndTransactionHolder conn, IOperableTrigger trigger)
 {
     try
     {
         Delegate.UpdateTriggerStateFromOtherState(conn, trigger.Key, StateWaiting, StateAcquired);
         Delegate.DeleteFiredTrigger(conn, trigger.FireInstanceId);
     }
     catch (Exception e)
     {
         throw new JobPersistenceException("Couldn't release acquired trigger: " + e.Message, e);
     }
 }
Ejemplo n.º 55
0
        /// <summary>
        /// Applies the misfire.
        /// </summary>
        /// <param name="tw">The trigger wrapper.</param>
        /// <returns></returns>
        protected virtual bool ApplyMisfire(IOperableTrigger trigger)
        {
            DateTimeOffset misfireTime = SystemTime.UtcNow();
            if (MisfireThreshold > TimeSpan.Zero)
            {
                misfireTime = misfireTime.AddMilliseconds(-1 * MisfireThreshold.TotalMilliseconds);
            }

            DateTimeOffset? tnft = trigger.GetNextFireTimeUtc();
            if (!tnft.HasValue || tnft.Value > misfireTime
                || trigger.MisfireInstruction == MisfireInstruction.IgnoreMisfirePolicy)
            {
                return false;
            }

            ICalendar cal = null;
            if (trigger.CalendarName != null)
            {
                cal = this.RetrieveCalendar(trigger.CalendarName);
            }

            signaler.NotifyTriggerListenersMisfired(trigger);

            trigger.UpdateAfterMisfire(cal);
            this.StoreTrigger(trigger, true);

            if (!trigger.GetNextFireTimeUtc().HasValue)
            {
                this.Triggers.Update(
                    Query.EQ("_id", trigger.Key.ToBsonDocument()),
                    Update.Set("State", "Complete"));

                signaler.NotifySchedulerListenersFinalized(trigger);
            }
            else if (tnft.Equals(trigger.GetNextFireTimeUtc()))
            {
                return false;
            }

            return true;
        }
 public static string GetDatabaseId(this IOperableTrigger trigger)
 {
     return($"{trigger.Key.Name}/{trigger.Key.Group}");
 }
Ejemplo n.º 57
0
        /// <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);
        }
Ejemplo n.º 58
0
 public bool CanHandleTriggerType(IOperableTrigger trigger)
 {
     return(trigger is CronTriggerImpl impl && !impl.HasAdditionalProperties);
 }
        /// <summary>
        /// The main processing loop of the <see cref="QuartzSchedulerThread" />.
        /// </summary>
        public override void Run()
        {
            bool lastAcquireFailed = false;

            while (!halted)
            {
                try
                {
                    // check if we're supposed to pause...
                    lock (sigLock)
                    {
                        while (paused && !halted)
                        {
                            try
                            {
                                // wait until togglePause(false) is called...
                                Monitor.Wait(sigLock, 1000);
                            }
                            catch (ThreadInterruptedException)
                            {
                            }
                        }

                        if (halted)
                        {
                            break;
                        }
                    }

                    int availThreadCount = qsRsrcs.ThreadPool.BlockForAvailableThreads();
                    if (availThreadCount > 0) // will always be true, due to semantics of blockForAvailableThreads...
                    {
                        IList <IOperableTrigger> triggers = null;

                        DateTimeOffset now = SystemTime.UtcNow();

                        ClearSignaledSchedulingChange();
                        try
                        {
                            triggers = qsRsrcs.JobStore.AcquireNextTriggers(
                                now + idleWaitTime, Math.Min(availThreadCount, qsRsrcs.MaxBatchSize), qsRsrcs.BatchTimeWindow);
                            lastAcquireFailed = false;
                            if (log.IsDebugEnabled)
                            {
                                log.DebugFormat("Batch acquisition of {0} triggers", (triggers == null ? 0 : triggers.Count));
                            }
                        }
                        catch (JobPersistenceException jpe)
                        {
                            if (!lastAcquireFailed)
                            {
                                qs.NotifySchedulerListenersError("An error occurred while scanning for the next trigger to fire.", jpe);
                            }
                            lastAcquireFailed = true;
                            continue;
                        }
                        catch (Exception e)
                        {
                            if (!lastAcquireFailed)
                            {
                                Log.Error("quartzSchedulerThreadLoop: RuntimeException " + e.Message, e);
                            }
                            lastAcquireFailed = true;
                            continue;
                        }

                        if (triggers != null && triggers.Count > 0)
                        {
                            now = SystemTime.UtcNow();
                            DateTimeOffset triggerTime      = triggers[0].GetNextFireTimeUtc().Value;
                            TimeSpan       timeUntilTrigger = triggerTime - now;

                            while (timeUntilTrigger > TimeSpan.FromMilliseconds(2))
                            {
                                if (ReleaseIfScheduleChangedSignificantly(triggers, triggerTime))
                                {
                                    break;
                                }
                                lock (sigLock)
                                {
                                    if (halted)
                                    {
                                        break;
                                    }
                                    if (!IsCandidateNewTimeEarlierWithinReason(triggerTime, false))
                                    {
                                        try
                                        {
                                            // we could have blocked a long while
                                            // on 'synchronize', so we must recompute
                                            now = SystemTime.UtcNow();
                                            timeUntilTrigger = triggerTime - now;
                                            if (timeUntilTrigger > TimeSpan.Zero)
                                            {
                                                Monitor.Wait(sigLock, timeUntilTrigger);
                                            }
                                        }
                                        catch (ThreadInterruptedException)
                                        {
                                        }
                                    }
                                }
                                if (ReleaseIfScheduleChangedSignificantly(triggers, triggerTime))
                                {
                                    break;
                                }
                                now = SystemTime.UtcNow();
                                timeUntilTrigger = triggerTime - now;
                            }

                            // this happens if releaseIfScheduleChangedSignificantly decided to release triggers
                            if (triggers.Count == 0)
                            {
                                continue;
                            }

                            // set triggers to 'executing'
                            IList <TriggerFiredResult> bndles = new List <TriggerFiredResult>();

                            bool goAhead = true;
                            lock (sigLock)
                            {
                                goAhead = !halted;
                            }

                            if (goAhead)
                            {
                                try
                                {
                                    IList <TriggerFiredResult> res = qsRsrcs.JobStore.TriggersFired(triggers);
                                    if (res != null)
                                    {
                                        bndles = res;
                                    }
                                }
                                catch (SchedulerException se)
                                {
                                    qs.NotifySchedulerListenersError("An error occurred while firing triggers '" + triggers + "'", se);
                                    // QTZ-179 : a problem occurred interacting with the triggers from the db
                                    // we release them and loop again
                                    foreach (IOperableTrigger t in triggers)
                                    {
                                        qsRsrcs.JobStore.ReleaseAcquiredTrigger(t);
                                    }
                                    continue;
                                }
                            }


                            for (int i = 0; i < bndles.Count; i++)
                            {
                                TriggerFiredResult result    = bndles[i];
                                TriggerFiredBundle bndle     = result.TriggerFiredBundle;
                                Exception          exception = result.Exception;

                                IOperableTrigger trigger = triggers[i];
                                // TODO SQL exception?
                                if (exception != null && (exception is DbException || exception.InnerException is DbException))
                                {
                                    Log.Error("DbException while firing trigger " + trigger, exception);
                                    qsRsrcs.JobStore.ReleaseAcquiredTrigger(trigger);
                                    continue;
                                }

                                // it's possible to get 'null' if the triggers was paused,
                                // blocked, or other similar occurrences that prevent it being
                                // fired at this time...  or if the scheduler was shutdown (halted)
                                if (bndle == null)
                                {
                                    qsRsrcs.JobStore.ReleaseAcquiredTrigger(trigger);
                                    continue;
                                }

                                // TODO: improvements:
                                //
                                // 2- make sure we can get a job runshell before firing trigger, or
                                //   don't let that throw an exception (right now it never does,
                                //   but the signature says it can).
                                // 3- acquire more triggers at a time (based on num threads available?)

                                JobRunShell shell = null;
                                try
                                {
                                    shell = qsRsrcs.JobRunShellFactory.CreateJobRunShell(bndle);
                                    shell.Initialize(qs);
                                }
                                catch (SchedulerException)
                                {
                                    qsRsrcs.JobStore.TriggeredJobComplete(trigger, bndle.JobDetail, SchedulerInstruction.SetAllJobTriggersError);
                                    continue;
                                }

                                if (qsRsrcs.ThreadPool.RunInThread(shell) == false)
                                {
                                    // this case should never happen, as it is indicative of the
                                    // scheduler being shutdown or a bug in the thread pool or
                                    // a thread pool being used concurrently - which the docs
                                    // say not to do...
                                    Log.Error("ThreadPool.runInThread() return false!");
                                    qsRsrcs.JobStore.TriggeredJobComplete(trigger, bndle.JobDetail, SchedulerInstruction.SetAllJobTriggersError);
                                }
                            }

                            continue; // while (!halted)
                        }
                    }
                    else // if(availThreadCount > 0)
                    {
                        // should never happen, if threadPool.blockForAvailableThreads() follows contract
                        continue;
                        // while (!halted)
                    }

                    DateTimeOffset utcNow            = SystemTime.UtcNow();
                    DateTimeOffset waitTime          = utcNow.Add(GetRandomizedIdleWaitTime());
                    TimeSpan       timeUntilContinue = waitTime - utcNow;
                    lock (sigLock)
                    {
                        if (!halted)
                        {
                            try
                            {
                                // QTZ-336 A job might have been completed in the mean time and we might have
                                // missed the scheduled changed signal by not waiting for the notify() yet
                                // Check that before waiting for too long in case this very job needs to be
                                // scheduled very soon
                                if (!IsScheduleChanged())
                                {
                                    Monitor.Wait(sigLock, timeUntilContinue);
                                }
                            }
                            catch (ThreadInterruptedException)
                            {
                            }
                        }
                    }
                }
                catch (Exception re)
                {
                    if (Log != null)
                    {
                        Log.Error("Runtime error occurred in main trigger firing loop.", re);
                    }
                }
            } // while (!halted)

            // drop references to scheduler stuff to aid garbage collection...
            qs      = null;
            qsRsrcs = null;
        }
Ejemplo n.º 60
0
 /// <see cref="IJobStore.ReplaceTrigger(TriggerKey, IOperableTrigger)" />
 public bool ReplaceTrigger(TriggerKey triggerKey, IOperableTrigger newTrigger)
 {
     return
         (bool)
         ExecuteInLock(LockTriggerAccess, conn => ReplaceTrigger(conn, triggerKey, newTrigger));
 }