예제 #1
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();
                }
            }
        }
예제 #2
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);
                }
            }
        }