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