Quartz重试作业,触发器的延迟时间策略呈指数增长

时间:2019-03-16 13:24:57

标签: java quartz-scheduler quartz

我在春季项目中使用石英。这个想法是为新的收入数据创建一个单独的工作,该工作没有成功地交付给目标服务。

  • 要以指数级增长的策略交付数据,我还要为下一次失败的尝试创建工作。 (它向数据库发送垃圾邮件。似乎可行,但可以做得更好。)
  • 不同的解决方案是创建可重复的基于crone的作业,该作业扫描数据库数据并仅加载日期,因为时间已过去,所以现在应该处理该日期(在这种情况下,我必须管理很多Java部分)。

两种方法都能提供正确的流程,但我更喜欢开箱即用的解决方案。

我试图管理JobExecutionContext触发的作业,以使用相同的JobDetailquartzScheduler中注册它。想法是用不同的触发器更新现有作业。但是问题是石英试图创建将其持久保存在数据库中的新作业。

org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'digex-caas-securepay.b333e5bf-583f-4643-9ad7-ef4b913001f7', because one already exists with this identification.
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeJob(JobStoreSupport.java:1113) ~[quartz-2.3.0.jar:na]
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$2.executeVoid(JobStoreSupport.java:1067) ~[quartz-2.3.0.jar:na]
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$VoidTransactionCallback.execute(JobStoreSupport.java:3765) ~[quartz-2.3.0.jar:na]
    at org.quartz.impl.jdbcjobstore.JobStoreSupport$VoidTransactionCallback.execute(JobStoreSupport.java:3763) ~[quartz-2.3.0.jar:na]
    at org.quartz.impl.jdbcjobstore.JobStoreCMT.executeInLock(JobStoreCMT.java:245) ~[quartz-2.3.0.jar:na]
    at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeJobAndTrigger(JobStoreSupport.java:1063) ~[quartz-2.3.0.jar:na]
    at org.quartz.core.QuartzScheduler.scheduleJob(QuartzScheduler.java:855) ~[quartz-2.3.0.jar:na]
    at org.quartz.impl.StdScheduler.scheduleJob(StdScheduler.java:249) ~[quartz-2.3.0.jar:na]
    at com.incomm.ecomm.services.quartz.OrderQuartzJobScheduler.registerSecurePayPostServiceJob(OrderQuartzJobScheduler.java:59) ~[classes/:na]

问题是(请回答任何):

  • 如何通过石英作业触发器更新进行管理(如果未成功处理-使用不同的触发时间更新触发器)?
  • 如何通过石英作业更新进行管理(如果未成功处理-使用新触发器更新作业)?
  • 如何为触发注册呈指数增长的延迟时间策略?

2 个答案:

答案 0 :(得分:1)

  • 您可以采用这种方法(重试机制,可以没有 允许重试)参考: Quartz retry when failure
  • 对于每个失败,您可以更新计数器并发送电子邮件。那么你 会在最大尝试中知道它是否成功通过。
  • 如果不晚一点,您将有一个仪表板来查看失败的(包括 可以尝试手动运行该机制。
  • 您可以立即设置时间轴,而不是e.setRefire。 120分钟后,根据JobDataMap机制安排运行它

答案 1 :(得分:1)

简单的答案是:

scheduler.rescheduleJob(trigger.getKey(), trigger);

详细的答案是:

  
      
  • 如何通过石英作业触发器更新进行管理
  •   

scheduler.rescheduleJob(trigger.getKey(),触发器);

  
      
  • 如何通过石英作业更新进行管理
  •   

如果触发器已更新,则不再重要。

  
      
  • 如何为触发注册呈指数增长的延迟时间策略?
  •   

单个触发器可以在任何不同的时间进行重新安排。可以使用IntervalCalculationStrategy的任何实现来计算下一次执行的时间。

重新安排作业的示例:

可以从JobExecutionContext获取职位和职位详细信息,但这不是必需的。触发器只能连接到一个作业,因此足以更新石英指定triggerKey

@Autowired
private Scheduler scheduler;
@Autowired
private IntervalCalculationStrategy intervalCalculation;

public <T extends QuartzJobBean> void registerSecurePayPostServiceJob(
    JobExecutionContext firedJobExecutionContext) {
  Optional<SimpleTriggerImpl> mutableTrigger =
      ofNullable(firedJobExecutionContext)
          .map(JobExecutionContext::getTrigger)
          .filter(SimpleTriggerImpl.class::isInstance)
          .map(SimpleTriggerImpl.class::cast);
  try {
    if (mutableTrigger.isPresent()) {
      SimpleTriggerImpl trigger = mutableTrigger.get();
      int nextAttemptNumber = trigger.getTimesTriggered();
      log.trace("trigger: {} fired [{}] times", trigger.getFullName(),
          trigger.getTimesTriggered());
      trigger.setStartTime(intervalCalculation.calculateNextTryDate(nextAttemptNumber));
      this.scheduler.rescheduleJob(trigger.getKey(), trigger);
    }
  } catch (SchedulerException e) {
    log.error("job was not rescheduled <{}>", firedJobExecutionContext.getJobDetail(), e);
  }
}