Quartz.net 中有原生的 misfire 处理,但它只指定作业是否应该立即再次触发,或者在一段时间后或在 misfire 后多次触发。
我认为一种选择是从 IncrementalImportJob 内部处理这个问题。
try
{
//download data
//import data
}
catch (Exception e) //something went wrong
{
//log the error
UpdateFullImportJobTrigger(sched);
}
//Reschedule FullImportJob to run at a time of your choosing.
public void UpdateFullImportJobTrigger(IScheduler sched)
{
Trigger oldTrigger = sched.getTrigger(triggerKey("oldTrigger", "group1");
TriggerBuilder tb = oldTrigger.getTriggerBuilder();
//if you want it to run based on a schedule use this:
Trigger newTrigger = tb.withSchedule(simpleSchedule()
.withIntervalInSeconds(10)
.withRepeatCount(10)
.build();
sched.rescheduleJob(oldTrigger.getKey(), newTrigger);
//or use simple trigger if you want it to run immediately and only once so that
//it runs again on schedule the next time.
}
这是一种方法。另一种方法是将这个逻辑抽象到一个维护作业中,该作业经常检查日志,如果它发现来自 IncrementalImportJob 的失败消息,它会触发 FullImportJob。但是,这在某种程度上取决于您的日志系统(大多数人使用 NLog 或 log4net)。
另一方面,如果您担心作业从一开始就没有运行,因为例如应用程序/数据库/服务器已关闭,您可以安排 FullImportJob 在几个小时后触发并检查 IncrementalImportJob 是否已触发如下:
//this is done from FullImportJob
//how you retrieve triggerKey will depend on whether
//you are using RAMJobStore or ADO.NET JobStore
public void Execute(IJobExecutionContext context)
{
ITrigger incImportJobTrigger = context.Scheduler.GetTrigger(triggerKey);
//if the job has been rescheduled with a new time quartz will set this to null
if (!incImportJobTrigger.GetPreviousFireTimeUtc().HasValue) return;
DateTimeOffset utcTime = incImportJobTrigger.GetPreviousFireTimeUtc().Value;
DateTime previousTireTime = utcTime.LocalDateTime;
if (previousTireTime.Day == DateTime.Now.Day) return;
//IncrementalImportJob has not ran today, let's run FullImportJob
}
希望这可以帮助。