I am seeing this issue where the same job with same job key and same job trigger is firing multiple times when running the job based on cron defined.
Quartz is defined with ThreadPool size of 3 and whenever the job runs quartz is using these 3 threads and runs the job almost 38 times ( this number is dynamic every time quartz runs the job).
Spring boot: 2.5.3 Quartz-scheduler: 2.3.2
Cron Expression:
Given the Quartz cron '* */3 * * * ? (every 3 minutes)' and reference date '2021-08-08T13:03:22.541936-04:00[America/New_York]'
Job execution output when running the job at every 3 mins:
=============== executing cron job =====================
Job Key: email-jobs.email-cron-job
Job Trigger Key: email-triggers.email-cron-job
Scheduler Name: service_ml_scheduler
Scheduler Id: nsimha-mac-11628442202262
Fire Instance Id: nsimha-mac-116284422022621628442202250
Thread Id: service_ml_scheduler_Worker-1
========================================================
=============== executing cron job =====================
Job Key : email-jobs.email-cron-job
Job Trigger Key: email-triggers.email-cron-job
Scheduler Name: service_ml_scheduler
Scheduler Id: nsimha-mac-11628442202262
Fire Instance Id: nsimha-mac-116284422022621628442202251
Thread Id: service_ml_scheduler_Worker-2
========================================================
=============== executing cron job =====================
Job Key: email-jobs.email-cron-job
Job Trigger Key: email-triggers.email-cron-job
Scheduler Name: service_ml_scheduler
Scheduler Id: nsimha-mac-11628442202262
Fire Instance Id: nsimha-mac-116284422022621628442202252
Thread Id: service_ml_scheduler_Worker-3
========================================================
=============== executing cron job =====================
Job Key: email-jobs.email-cron-job
Job Trigger Key: email-triggers.email-cron-job
Scheduler Name: service_ml_scheduler
Scheduler Id: nsimha-mac-11628442202262
Fire Instance Id: nsimha-mac-116284422022621628442202253
Thread Id: service_ml_scheduler_Worker-1
========================================================
=============== executing cron job =====================
Job Key: email-jobs.email-cron-job
Job Trigger Key: email-triggers.email-cron-job
Scheduler Name: service_ml_scheduler
Scheduler Id: nsimha-mac-11628442202262
Fire Instance Id: nsimha-mac-116284422022621628442202254
Thread Id: service_ml_scheduler_Worker-2
========================================================
=============== executing cron job =====================
Job Key: email-jobs.email-cron-job
Job Trigger Key: email-triggers.email-cron-job
Scheduler Name: service_ml_scheduler
Scheduler Id: nsimha-mac-11628442202262
Fire Instance Id: nsimha-mac-116284422022621628442202255
Thread Id: service_ml_scheduler_Worker-3
========================================================
mysql> select * from QRTZ_TRIGGERS;
+----------------------+----------------+----------------+----------------+------------+--------------------+----------------+----------------+----------+---------------+--------------+---------------+----------+---------------+---------------+--------------------+
| SCHED_NAME | TRIGGER_NAME | TRIGGER_GROUP | JOB_NAME | JOB_GROUP | DESCRIPTION | NEXT_FIRE_TIME | PREV_FIRE_TIME | PRIORITY | TRIGGER_STATE | TRIGGER_TYPE | START_TIME | END_TIME | CALENDAR_NAME | MISFIRE_INSTR | JOB_DATA |
+----------------------+----------------+----------------+----------------+------------+--------------------+----------------+----------------+----------+---------------+--------------+---------------+----------+---------------+---------------+--------------------+
| service_ml_scheduler | email-cron-job | email-triggers | email-cron-job | email-jobs | Send Email Trigger | 1628443488000 | 1628443487000 | 5 | ACQUIRED | CRON | 1628443286000 | 0 | NULL | 0 | NULL |
+----------------------+----------------+----------------+----------------+------------+--------------------+----------------+----------------+----------+---------------+--------------+---------------+----------+---------------+---------------+--------------------+
1 row in set (0.00 sec)
mysql> select * from QRTZ_CRON_TRIGGERS;
+----------------------+----------------+----------------+-----------------+------------------+
| SCHED_NAME | TRIGGER_NAME | TRIGGER_GROUP | CRON_EXPRESSION | TIME_ZONE_ID |
+----------------------+----------------+----------------+-----------------+------------------+
| service_ml_scheduler | email-cron-job | email-triggers | * */3 * * * ? | America/New_York |
+----------------------+----------------+----------------+-----------------+------------------+
1 row in set (0.00 sec)
mysql> select SCHED_NAME, JOB_NAME, JOB_GROUP, DESCRIPTION, JOB_CLASS_NAME, IS_DURABLE, IS_NONCONCURRENT, IS_UPDATE_DATA, REQUESTS_RECOVERY from QRTZ_JOB_DETAILS;
+----------------------+----------------+------------+----------------+------------------------------------------+------------+------------------+----------------+-------------------+
| SCHED_NAME | JOB_NAME | JOB_GROUP | DESCRIPTION | JOB_CLASS_NAME | IS_DURABLE | IS_NONCONCURRENT | IS_UPDATE_DATA | REQUESTS_RECOVERY |
+----------------------+----------------+------------+----------------+------------------------------------------+------------+------------------+----------------+-------------------+
| service_ml_scheduler | email-cron-job | email-jobs | Send Email Job | com.example.springquartz.crons.SampleJob | 1 | 1 | 0 | 0 |
+----------------------+----------------+------------+----------------+------------------------------------------+------------+------------------+----------------+-------------------+
1 row in set (0.00 sec)
private static JobDetail buildJobDetail() {
return JobBuilder.newJob(SampleJob.class)
.withIdentity("email-cron-job", "email-jobs")
.withDescription("Send Email Job")
.usingJobData(new JobDataMap())
.storeDurably()
.build();
}
private static Trigger buildJobTrigger(JobDetail jobDetail, ZonedDateTime startAt) {
return TriggerBuilder.newTrigger()
.forJob(jobDetail)
.withIdentity(jobDetail.getKey().getName(), "email-triggers")
.withDescription("Send Email Trigger")
.startAt(Date.from(startAt.toInstant()))
.withSchedule(CronScheduleBuilder.cronSchedule("* */3 * * * ?")
.withMisfireHandlingInstructionIgnoreMisfires())
.build();
}
@DisallowConcurrentExecution
public class SampleJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
String jobKey = context.getJobDetail().getKey().toString();
String jobTrigger = context.getTrigger().getKey().toString();
String schedulerName = "";
String schedulerId = "";
try {
schedulerName = context.getScheduler().getSchedulerName();
schedulerId = context.getScheduler().getSchedulerInstanceId();
} catch (SchedulerException e) {
e.printStackTrace();
}
System.out.println("=============== executing cron job =====================");
System.out.println("Job Key: " + jobKey);
System.out.println("Job Trigger Key : " + jobTrigger);
System.out.println("Scheduler Name: " + schedulerName);
System.out.println("Scheduler Id: " + schedulerId);
System.out.println("Fire Instance Id: " + context.getFireInstanceId());
System.out.println("Thread Id: " + Thread.currentThread().getName());
System.out.println("========================================================");
//System.out.println("this is inside the job execution " + Thread.currentThread().getName());
}
}
Sample application can be found at https://github.com/quartz-scheduler/quartz/files/6954758/SpringQuartz.tar.gz