在今天迭代上线后,测试突然发现了一个bug.去pro环境看了一下log
2019-08-02 17:52:40.756 ERROR 18408 --- [nio-8084-exec-2] c.g.common.eventbus.EventBus.default : Exception thrown by subscriber method onEvent(com.decobim.todo.job.InAddTriggerEvent) on subscriber com.decobim.ops.quartz.QuartzEvent@6e9ea96d when dispatching event: InAddTriggerEvent(todoItemId=1183894449946624, reminderTime=1564743006000)
org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'todoJobGroup.1183894449946624', 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.decobim.ops.quartz.QuartzEvent.onEvent(QuartzEvent.java:56) ~[classes/:na]
错误描述是 org.quartz.ObjectAlreadyExistsException: Unable to store Job : 'todoJobGroup.1183894449946624', because one already exists with this identification.
不能存储job,因为相同的job已经存在了.
那就很容易解决,问题出现在这行:
//at com.decobim.ops.quartz.QuartzEvent.onEvent(QuartzEvent.java:56) ~[classes/:na]
//相应代码为:
scheduler.scheduleJob(job, trigger);
因为相同的job名已经存在,所以要做的就是删除之前的该名称的job. 问题出现在,本应该被删除的job,实际是被暂停了.又去翻了一下Scheduler的代码,看了一下注释(注释写的真的挺全的)
/**
* Pause the <code>{@link Trigger}</code> with the given key.
*
* @see #resumeTrigger(TriggerKey)
*/
void pauseTrigger(TriggerKey triggerKey)
throws SchedulerException;
/**
* Remove the indicated <code>{@link Trigger}</code> from the scheduler.
*
* <p>If the related job does not have any other triggers, and the job is
* not durable, then the job will also be deleted.</p>
*/
boolean unscheduleJob(TriggerKey triggerKey)
throws SchedulerException;
之前用的是pauseTrigger
作用只是暂停这个trigger,实际应该用unscheduleJob
//scheduler.pauseTrigger(new TriggerKey(todoItemId, TODO_TRIGGER_GROUP));
// 修改为
// 从pause改为unSchedule pause只是暂停,unSchedule是从数据库中删除
scheduler.unscheduleJob(new TriggerKey(todoItemId, TODO_TRIGGER_GROUP));
在scheduleJob这边也做个防范:
/**
* Remove (delete) the <code>{@link org.quartz.Trigger}</code> with the
* given key, and store the new given one - which must be associated
* with the same job (the new trigger must have the job name & group specified)
* - however, the new trigger need not have the same name as the old trigger.
*
* @param triggerKey identity of the trigger to replace
* @param newTrigger
* The new <code>Trigger</code> to be stored.
*
* @return <code>null</code> if a <code>Trigger</code> with the given
* name & group was not found and removed from the store (and the
* new trigger is therefore not stored), otherwise
* the first fire time of the newly scheduled trigger is returned.
*/
Date rescheduleJob(TriggerKey triggerKey, Trigger newTrigger)
throws SchedulerException;
//scheduler.scheduleJob(job, trigger);
// 修改为:
try {
scheduler.scheduleJob(job, trigger);
}catch (ObjectAlreadyExistsException e){
// 放置出现triggerKey相同的情况,无论如何 后添加的trigger要覆盖老trigger
TriggerKey triggerKey = new TriggerKey(todoItemId, TODO_TRIGGER_GROUP);
scheduler.rescheduleJob(triggerKey,trigger);
}