0

假设我有两个 Quartz.net 工作

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

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

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

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

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

4

1 回答 1

0

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 
}

希望这可以帮助。

于 2013-08-25T00:14:41.690 回答