Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quartz Jobs are not running in parallel #1304

Open
alfespa17 opened this issue Feb 3, 2025 · 0 comments
Open

Quartz Jobs are not running in parallel #1304

alfespa17 opened this issue Feb 3, 2025 · 0 comments

Comments

@alfespa17
Copy link

I am using quartz 2.5.0 and spring-boot 3.3.7 and it looks like the jobs are not being executed in parallel, not sure if this is a bug or maybe I am missing something in my configuration, I hope someone can help me.

I have the following configuration to setup the quartz scheduler inside my spring application

@Configuration
public class QuartzAutoConfiguration {

    class AutowireCapableBeanJobFactory extends SpringBeanJobFactory {

        private final AutowireCapableBeanFactory beanFactory;

        @Autowired
        public AutowireCapableBeanJobFactory(AutowireCapableBeanFactory beanFactory) {
            Assert.notNull(beanFactory, "Bean factory must not be null");
            this.beanFactory = beanFactory;
        }

        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            Object jobInstance = super.createJobInstance(bundle);
            this.beanFactory.autowireBean(jobInstance);
            this.beanFactory.initializeBean(jobInstance, "jobInstance");
            return jobInstance;
        }
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(ApplicationContext applicationContext, DataSource dataSource, DataSourceConfigurationProperties dataSourceConfigurationProperties) {
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        schedulerFactoryBean.setJobFactory(new AutowireCapableBeanJobFactory(applicationContext.getAutowireCapableBeanFactory()));
        schedulerFactoryBean.setDataSource(dataSource);
        Properties properties = new Properties();
        properties.put("org.quartz.jobStore.class","org.springframework.scheduling.quartz.LocalDataSourceJobStore");
        properties.put("org.quartz.jobStore.isClustered","true");
        properties.put("org.quartz.scheduler.instanceId","AUTO");
        switch(dataSourceConfigurationProperties.getType()){
            case SQL_AZURE:
                properties.put("org.quartz.jobStore.driverDelegateClass","org.quartz.impl.jdbcjobstore.MSSQLDelegate");
                break;
            case POSTGRESQL:
                properties.put("org.quartz.jobStore.driverDelegateClass","org.quartz.impl.jdbcjobstore.PostgreSQLDelegate");
                break;
            default:
                properties.put("org.quartz.jobStore.driverDelegateClass","org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
                break;
        }
        schedulerFactoryBean.setQuartzProperties(properties);
        return schedulerFactoryBean;
    }

    @Bean
    public Scheduler scheduler(SchedulerFactoryBean schedulerFactoryBean) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        scheduler.start();
        return scheduler;
    }

}

I am creating the quartz job using the following:

public void createJobContextNow(Job job) throws SchedulerException {

        String random = UUID.randomUUID().toString();
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put(ScheduleJob.JOB_ID, job.getId());
        jobDataMap.put("isTriggerFromStatusChange", "true");
        jobDataMap.put("identity", PREFIX_JOB_CONTEXT + job.getId() + "_" + random);

        JobDetail jobDetail = JobBuilder.newJob().ofType(ScheduleJob.class)
                .storeDurably()
                .setJobData(jobDataMap)
                .withIdentity(PREFIX_JOB_CONTEXT + job.getId() + "_" + random)
                .withDescription(String.valueOf(job.getId()))
                .build();

        Trigger trigger = TriggerBuilder.newTrigger()
                .forJob(jobDetail)
                .withIdentity(PREFIX_JOB_CONTEXT + job.getId() + "_" + random)
                .withDescription(String.valueOf(job.getId()))
                .startNow()
                .build();

        log.info("Running Job Context Now: {}, Identity: {}", job.getId(),
                PREFIX_JOB_CONTEXT + job.getId() + "_" + random);
        scheduler.scheduleJob(jobDetail, trigger);
    }

When my application is starting I see the following quartz logs.

2025-02-03T22:19:46.957Z  INFO 1 --- [           main] org.quartz.core.SchedulerSignalerImpl    : Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2025-02-03T22:19:46.958Z  INFO 1 --- [           main] org.quartz.core.QuartzScheduler          : Quartz Scheduler v2.5.0 created.
2025-02-03T22:19:46.984Z  INFO 1 --- [           main] o.s.s.quartz.LocalDataSourceJobStore     : Using db table-based data access locking (synchronization).
2025-02-03T22:19:46.988Z  INFO 1 --- [           main] o.s.s.quartz.LocalDataSourceJobStore     : JobStoreCMT initialized.
2025-02-03T22:19:46.995Z  INFO 1 --- [           main] org.quartz.core.QuartzScheduler          : Scheduler meta-data: Quartz Scheduler (v2.5.0) 'schedulerFactoryBean' with instanceId 'terrakube-api-fb67864f6-gj5cs1738621186939'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.springframework.scheduling.quartz.LocalDataSourceJobStore' - which supports persistence. and is clustered.

2025-02-03T22:19:46.995Z  INFO 1 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler 'schedulerFactoryBean' initialized from an externally provided properties instance.
2025-02-03T22:19:46.996Z  INFO 1 --- [           main] org.quartz.impl.StdSchedulerFactory      : Quartz scheduler version: 2.5.0

I was checking the documentation in the following link and I added the following properties but it is not working to run job in parallel.

        properties.put("org.quartz.jobStore.acquireTriggersWithinLock","true");
        properties.put("org.quartz.scheduler.batchTriggerAcquisitionMaxCount",10);

Finally I am implementing the job like the following without using @DisallowConcurrentExecution

public class ScheduleJob implements org.quartz.Job {
    ...

    @Transactional
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        int jobId = jobExecutionContext.getJobDetail().getJobDataMap().getInt(JOB_ID);

Even if I added multiple pod in my application jobs are running sequentially but are executed in different instances.

Any suggestion to make the jobs run in parallel?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant