当另一个作业没有运行一段时间时,如何配置Quartz.net来运行作业

时间:2013-08-24 21:38:00

标签: c# quartz.net

假设我有两个Quartz.net作业

  • 下载包含一段时间(例如24小时)变化增量的CSV文件,然后导入数据(称为IncrementalImportJob
  • 下载包含所有记录的CSV文件,然后导入数据(称为FullImportJob

要求是IncrementalImportJob至少一段时间(例如24小时)。如果错过了该窗口,或者作业未成功完成,则应运行FullImportJob。原因是不会导入该(错过)日的更改。这种情况非常特殊。

FullImportJob需要资源(时间,CPU,数据库,内存)来导入所有数据,这可能会影响其他系统。此外,变化的增量通常很小或不存在。因此,我们的目标是尽可能支持运行IncrementalImportJob

如果FullImportJob在特定时间段(例如24小时)内未成功完成,那么如何配置quartz.net来运行IncrementalImportJob

在网上搜索“quartz.net recovery”和“quartz.net misfire”并未显示其是否受支持或是否可能。

1 个答案:

答案 0 :(得分:0)

在quartz.net中存在本机失火处理,但它只能指定作业是否应该触发immediately again, or after a period of time or a number of times after misfiring.

我认为一个选项是从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 
}

希望这有帮助。