【问题标题】:Quartz retry job with exponentially increasing delay time strategy for triggerQuartz 重试作业,触发器的延迟时间策略呈指数增长
【发布时间】:2019-03-16 13:24:56
【问题描述】:

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

  • 为了以指数级增长的策略提供数据,我还为下一次不成功的尝试创建了工作。 (它会向 DB 发送垃圾邮件。它似乎有效,但可能会更好。)
  • 不同的是,我的解决方案是创建可重复的基于 crone 的作业,该作业扫描 DB 数据并仅加载日期,因为时间过去了(在这种情况下,我必须在 java 部分进行大量管理)。

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

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

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]

问题是(请回答任何问题):

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

【问题讨论】:

    标签: java quartz-scheduler quartz


    【解决方案1】:
    • 你可以按照这个方法(重试机制并且可以有no. of 允许重试)参考: Quartz retry when failure
    • 对于每次失败,您都可以更新计数器并发送电子邮件。那么你 将在最大尝试中知道它是否成功通过。
    • 如果不是稍后,您将有一个仪表板来查看失败的(包括 no.of 次尝试)并且可以手动运行它。
    • 您可以设置时间线,而不是 e.setRefireImmediately。 120 分钟后,调度运行它,即基于 JobDataMap 机制

    【讨论】:

      【解决方案2】:

      简单的答案是:

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

      详细答案是:

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

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

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

      万一触发器更新,这不再重要了。

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

      可以用任何不同的时间重新安排单个触发器。可以使用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);
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-07-31
        • 2010-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多