I am using Sling's scheduler to schedule periodic jobs and I'm wondering if I'm scheduling job A to run every 5 minute. In the unlikely occasion, the job start to run and took more than 5 minute what will happen? I have specified the job cannot run in parallel.
Job A will run again immediately after the previous run finishes.
Job A will run 5 minute after the previous run finishes.
Under the hood, Sling's scheduler is using QuartzScheduler, so if you know how QuartzScheduler will behave in this case please do share your knowledge as well.
Any help is much appreciated!
In Quartz Scheduler 2.1.x the annotation DisallowConcurrentExecution is used to prevent concurrent execution of the same Job.
In Quartz Scheduler 2.0.x in order to void the concurrent execution of a Job you have to implement the StatefulJob interface.
The decision on whether the misfired execution will execute when the previous job completes or it will be ignored depends on the trigger's misfire policy. By default when the scheduler starts, it searches for any persistent triggers that have misfired, and it then updates each of them based on their individually configured misfire instructions.
So in my opinion Job A will run again immediately after the previous run finishes. I suppose that Sling uses the default misfire policy. Otherwise the answer depends on the misfire policy selection.
That's how Quartz Scheduler works. I don't know how the Sling's scheduler works.
I hope this helps.
Related
We have a project that uses somewhere around ten Quartz jobs via the aforementioned dependency. Everything seemed to work fine for a while but we have two jobs that just randomly stop working (all jobs are scheduled to run every five seconds). Our mitigation strategy was to migrate these jobs to Spring's 'own' scheduling as they do not require any input data. After adding #EnableScheduling and the appropriate #Scheduled annotation, they work fine and run every five seconds. The problem is that now, the 'old' Quartz jobs seemed to have stopped working (at least in our integration tests, they wait 20 seconds for an execution). The Quartz jobs just never fire. When increasing the timeout, the Quartz jobs sometimes start about 30 seconds after being scheduled. While they are running, the Spring jobs seem to wait. We have tried setting the thread count for both Quartz and Spring to > 50 but nothing seems to help. We're somewhat out of ideas, does anybody know a solution?
We're using Spring Boot 2.3.3. and the latest Quartz, 2.3.2.
Thanks.
Ok so the problem seems to be with our #Transactional management - we seem to have somehow acquired a lock that blocks Quartz's scheduler from finding triggers that were scheduled for immediate execution (Quartz trigger does not fire immediately seems to have the same problem, but unrelated to Spring scheduling). We 'fixed' the problem by setting
spring.quartz.properties.org.quartz.scheduler.idleWaitTime=5000
This is obviously not a fix but instead of waiting for 30 seconds (the default for Quartz's idle wait time which initially made the jobs only being executed after said time), the scheduler only waits for five seconds to search for triggers after not finding one. This makes our immediate jobs trigger five seconds late but that isn't a problem in our use case.
Of course, this isn't the real solution, refining our #Transactionals would probably be the correct fix but we cannot do that right now, maybe sometime in the future.
Why the problem started ocurring after #EnableScheduling and not beforehand, we have no idea.
I observed that jobs which are normally scheduled at midnight (but could not be executed because the server went into energy saving mode) get executed after the server comes out of energy saving mode. This leads to unexpected execution times.
Is there a way to tell Quartz to not execute jobs after they are too far behind their target time?
Yes. You just need to tell Quartz what to do about job misfires:
Another important property of a Trigger is its “misfire instruction”. A misfire occurs if a persistent trigger “misses” its firing time because of the scheduler being shutdown, or because there are no available threads in Quartz’s thread pool for executing the job. The different trigger types have different misfire instructions available to them. By default they use a ‘smart policy’ instruction - which has dynamic behavior based on trigger type and configuration. When the scheduler starts, it searches for any persistent triggers that have misfired, and it then updates each of them based on their individually configured misfire instructions. When you start using Quartz in your own projects, you should make yourself familiar with the misfire instructions that are defined on the given trigger types, and explained in their JavaDoc.
The specific misfire instruction depends on the Trigger type you're using. For a daily job It could be something like this:
trigger = newTrigger()
.withIdentity("trigger1", "group1")
.withSchedule(dailyAtHourAndMinute(0,0)
.withMisfireHandlingInstructionDoNothing()) // set misfire instruction
.build();
But again, it depends on the type of trigger. Just use your IDE to see what withMisfire*() methods are available, and use either withMisfireHandlingInstructionDoNothing or withMisfireHandlingInstructionNextWithRemainingCount (both will ignore the missed execution and wait for the next scheduled one).
When I had to learn about the different types of misfire instructions, besides Quartz's tutorials and API documentation, I used this blog entry.
I have 56 jobs scheduled as cronTrigger, all at an exact same time.
I expect these jobs all start executing together, without having any sequence.
like each one executing in it's own Thread. however quartz scheduler executes them one by one.
I did some research, and found this
Quartz Thread Execution Parallel or Sequential? that suggest setting of following properties in quartz.properties file:
org.quartz.scheduler.batchTriggerAcquisitionMaxCount = 60
org.quartz.threadPool.threadCount = 60
sad to say, it didn't work for me. still when one of my jobs encounters an exception, it keeps trying to run the job, which is fine, but other jobs never execute until this one totally fails after some attemps.
Do you know how to make the scheduler to exhibit a parallel behavior?
Thanks.
I'd like to use quartz in a project of mine. I know that there is a scheduler and a threadpool for the jobs.
Does the scheduler continuously run in its own thread and fires off the jobs?
If I run the app on a 2 core CPU will one core be busy with the scheduling thread?
Yes, quartz uses at least n+1 threads where 1 is the scheduler thread that is running in an infinite loop sleeping before next task that should be triggered. N is the number of worker threads in the threadpool. You can configure this number using the property org.quartz.threadPool.threadCount.
You can see it work by running the stuff through for example Eclipse and then in the debug view you can see the active and sleeping threads of the application.
Quartz will create a configurable pool of threads. Each job will fire in its own thread (of course, otherwise they can't run concurrently). And no, its not a busy loop so the scheduler won't claim a CPU for itself.
What would be the best way to schedule an event to run every Monday at 00:00?
Note though the app is running 24/7. So OS based schedulers such as cron are not needed.
You could embed a Quartz Scheduler in your Java app if it's a long running app. Quartz is a very flexible/powerful scheduler that can be configured in many ways.
Alternatively, if you simply want to run a Java process at a particular time then you should look at cron.
Edit: Given that your app is 24/7 (noting comments above), Quartz is definitely the way forward.
I think cron4J may be your best bet. You can then configure it to run at ceratin times.
Us the OS scheduler; either cron, Windows task scheduler or similar