Quartz 重试作业,触发器的延迟时间策略呈指数增长
Quartz retry job with exponentially increasing delay time strategy for trigger
我在 spring 项目中使用石英。这个想法是为新的收入数据创建单独的作业,这些数据没有成功传送到目标服务。
- 为了以指数增长的策略传递数据,我还为下一次不成功的尝试创造了工作。 (它向 DB 发送垃圾邮件。它似乎有效,但可以做得更好。)
- 不同的是,我的解决方案是创建可重复的基于 crone 的作业,扫描数据库数据并只加载日期,因为时间过去了(在这种情况下,我必须在 java 部分管理很多) .
两种方式都可以提供正确的流程,但我更喜欢开箱即用的解决方案。
我尝试管理 JobExecutionContext
触发作业以使用相同的 JobDetail
在 quartzScheduler
中注册它。这个想法是用不同的触发器更新现有的工作。但问题是 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.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]
问题是(请回答任何一个):
- 如何通过 quartz 作业触发器更新进行管理(以防未成功处理 - 使用不同触发时间更新触发器)?
- 如何通过 quartz 作业更新进行管理(以防未成功处理 - 使用新触发器更新作业)?
- 如何为触发器注册指数增长的延迟时间策略?
- 你可以按照这个方法(重试机制,可以没有。
允许重试)参考:
Quartz retry when failure
- 对于每次失败,您都可以更新计数器并发送电子邮件。那么你
在最大尝试中也会知道它是否成功通过。
- 如果不是稍后,您将有一个仪表板来查看失败的(包括
no.of 次尝试)并且可以 运行 手动机制。
- 您可以设置时间线,而不是 e.setRefireImmediately。 120 分钟后,调度到 运行 它即基于 JobDataMap 机制
简单的答案是:
scheduler.rescheduleJob(trigger.getKey(), trigger);
详细答案是:
- How to manage via quartz job trigger updates
scheduler.rescheduleJob(trigger.getKey(), 触发器);
- How to manage via quartz job updates
万一更新触发器就不再重要了。
- How to register exponentially increasing delay time strategy for 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);
}
}
我在 spring 项目中使用石英。这个想法是为新的收入数据创建单独的作业,这些数据没有成功传送到目标服务。
- 为了以指数增长的策略传递数据,我还为下一次不成功的尝试创造了工作。 (它向 DB 发送垃圾邮件。它似乎有效,但可以做得更好。)
- 不同的是,我的解决方案是创建可重复的基于 crone 的作业,扫描数据库数据并只加载日期,因为时间过去了(在这种情况下,我必须在 java 部分管理很多) .
两种方式都可以提供正确的流程,但我更喜欢开箱即用的解决方案。
我尝试管理 JobExecutionContext
触发作业以使用相同的 JobDetail
在 quartzScheduler
中注册它。这个想法是用不同的触发器更新现有的工作。但问题是 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.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]
问题是(请回答任何一个):
- 如何通过 quartz 作业触发器更新进行管理(以防未成功处理 - 使用不同触发时间更新触发器)?
- 如何通过 quartz 作业更新进行管理(以防未成功处理 - 使用新触发器更新作业)?
- 如何为触发器注册指数增长的延迟时间策略?
- 你可以按照这个方法(重试机制,可以没有。 允许重试)参考: Quartz retry when failure
- 对于每次失败,您都可以更新计数器并发送电子邮件。那么你 在最大尝试中也会知道它是否成功通过。
- 如果不是稍后,您将有一个仪表板来查看失败的(包括 no.of 次尝试)并且可以 运行 手动机制。
- 您可以设置时间线,而不是 e.setRefireImmediately。 120 分钟后,调度到 运行 它即基于 JobDataMap 机制
简单的答案是:
scheduler.rescheduleJob(trigger.getKey(), trigger);
详细答案是:
- How to manage via quartz job trigger updates
scheduler.rescheduleJob(trigger.getKey(), 触发器);
- How to manage via quartz job updates
万一更新触发器就不再重要了。
- How to register exponentially increasing delay time strategy for 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);
}
}