简体   繁体   English

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

[英]How does one configure Quartz.net to run a job when another job hasn't run for a period

Assume I have two Quartz.net jobs that 假设我有两个Quartz.net作业

  • downloads a CSV file with a delta of changes for a period (eg 24h) and then imports the data (called IncrementalImportJob ) 下载一段时间内(例如24h)具有变化增量的CSV文件,然后导入数据(称为IncrementalImportJob
  • downloads a CSV file with a all the records and then imports the data (called FullImportJob ) 下载包含所有记录的CSV文件,然后导入数据(称为FullImportJob

The requirement is that IncrementalImportJob at a minimum once for the period (eg 24h). 要求是在该时间段内(例如24h)至少要执行一次IncrementalImportJob If that window is missed, or the job didn't complete successfully, then FullImportJob should run instead. 如果错过了该窗口,或者作业未成功完成,则应改为运行FullImportJob The reason is that changes for that (missed) day would not be imported. 原因是当天(缺失)的更改不会被导入。 This condition is rather exceptional. 这种情况非常特殊。

The FullImportJob requires resources (time, CPU, database, memory) to import all the data, which may impact other systems. FullImportJob需要资源(时间,CPU,数据库,内存)来导入所有数据,这可能会影响其他系统。 Further, the delta of changes are often minimal or non-existent. 此外,变化的增量通常很小或根本不存在。 So the goal is to favour running the IncrementalImportJob when possible. 因此,目标是尽可能支持运行IncrementalImportJob

How does one configure quartz.net to run FullImportJob if IncrementalImportJob hasn't completed successfully in a specific time period (say 24h)? 如果IncrementalImportJob在特定时间段内(例如24小时)未成功完成,如何配置quartz.net以运行FullImportJob

Searching the web for "quartz.net recovery" and "quartz.net misfire" doesn't reveal whether its supported or whether its even possible. 在网络上搜索“ quartz.net恢复”和“ quartz.net失火”并不能显示其是否受支持甚至是否可能。

There is native misfire handling in quartz.net, however it only goes as far as specifying whether the job should fire immediately again, or after a period of time or a number of times after misfiring. quartz.net中有本机的失火处理,但是它只能说明是否应立即重新启动该作业,还是应在失火后一段时间或多次启动。

I think one option is to handle this internally from IncrementalImportJob. 我认为一种选择是从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.
}

This is one way of doing it. 这是一种方法。 Another would be abstracting this logic to a maintenance job that checks the logs every so often and if it finds a failure message from IncrementalImportJob, it fires FullImportJob. 另一个方法是将该逻辑抽象为维护工作,该工作经常检查日志,如果发现来自IncrementalImportJob的失败消息,则会触发FullImportJob。 However, this depends to some extent on your logging system (most people use NLog or log4net). 但是,这在某种程度上取决于您的日志系统(大多数人使用NLog或log4net)。

If on the other hand, your concern is that the job never ran in the first place because, for instance, the app/database/server was down, you could schedule FullImportJob to fire a few hours later and check if IncrementalImportJob has fired as follows: 另一方面,如果您担心该作业永远不会因为例如应用程序/数据库/服务器关闭而开始运行,则可以安排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 
}

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM