Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quartz Java resuming a job executes it many times

Tags:

For my application I create jobs and schedule them with CronTriggers. Each job has only one trigger and both the job name and the trigger names are the same. No jobs share a trigger.

Now when i create a cron trigger like this "0/1 * * * * ?" which instructs the job to execute every second, it works just fine.

The problem rises when I first pause the job by calling:

scheduler.pauseJob(jobName, jobGroup); 

and then resuming the job after let's say 50 seconds with:

scheduler.resumeJob(jobName, jobGroup); 

What I see is that for these 50 seconds the job did not execute as requested. But the moment I resume the job I see 50 executions of the job at the same time!!!

I thought that this was due to the default setting for the misfire instruction but even after setting the trigger's misfire instruction upon creation to this:

trigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING); 

The same thing happens. Can anyone suggest a way to fix this?

like image 479
Savvas Dalkitsis Avatar asked Dec 19 '09 18:12

Savvas Dalkitsis


People also ask

How do you trigger multiple jobs in quartz scheduler?

If you want to schedule multiple jobs in your console application you can simply call Scheduler. ScheduleJob (IScheduler) passing the job and the trigger you've previously created: IJobDetail firstJob = JobBuilder. Create<FirstJob>() .

How does quartz work in Java?

Quartz scheduler allows an enterprise to schedule a job at a specified date and time. It allows us to perform the operations to schedule or unschedule the jobs. It provides operations to start or stop or pause the scheduler. It also provides reminder services.

How does quartz clustering work?

Quartz's clustering features bring both high availability and scalability to your scheduler via fail-over and load balancing functionality. Clustering currently only works with the JDBC-Jobstore (JobStoreTX or JobStoreCMT), and essentially works by having each node of the cluster share the same database.

How do I Unschedule a quartz job?

We can unschedule a Job by calling the unschedule() method of the Scheduler class and passing the TriggerKey . If the related job does not have any other triggers, and the job is not durable, then the job will also be deleted.


1 Answers

The CronTrigger works by remembering the nextFireTime. After creating the trigger the nextFireTime is initialized. Every time the job is triggered nextFireTime is updated. Since the job is not triggered when paused nextFireTime remains "old". So after you resume the job the trigger will return every old trigger time.

The problem is, the trigger doesn't know it is being paused. To overcome this there is this misfire handling. After resuming the jobs the trigger's updateAfterMisfire() method will be invoked which corrects the nextFireTime. But not if the difference between nextFireTime and now is smaller than the misfireThreshold. Then the method is never called. This threshold's default value is 60,000. Thus if your pause period would be longer than 60s everything would be fine.

Since you have problems I assume it is not. ;) To workaround this you can modify the threshold or use a simple wrapper around CronTrigger:

public class PauseAwareCronTrigger extends CronTrigger {     // constructors you need go here      @Override     public Date getNextFireTime() {         Date nextFireTime = super.getNextFireTime();         if (nextFireTime.getTime() < System.currentTimeMillis()) {             // next fire time after now             nextFireTime = super.getFireTimeAfter(null);             super.setNextFireTime(nextFireTime);         }         return nextFireTime;     } } 
like image 111
Eduard Wirch Avatar answered Oct 16 '22 06:10

Eduard Wirch