Quartz run job again N minutes after completed - java

I have some repeating quartz jobs that use SimpleScheduleBuilder.repeatMinutelyForever(60). Lets say the job initially gets scheduled at 10:02am and runs for 5 minutes completing at 10:07am.
Right now it is getting scheduled to run again at 11:02am but I want it to run again 60 minutes after completing so it should be scheduled at 11:07am instead.
Is there any way to change the scheduling to do this? Or should I use a one time job that creates a new job each time it completes?

Use TriggerListener - see here for some examples in Quartz cookbook.
You will override triggerComplete and in there you will add your rescheduling code:
public void triggerComplete(Trigger trigger, JobExecutionContext context, CompletedExecutionInstruction triggerInstructionCode) {
// check here the triggerInstructionCode value and reschedule your job
super.triggerComplete(trigger, context, triggerInstructionCode);
}
Example for registering a TriggerListener with the scheduler to listen to a specific trigger:
scheduler.getListenerManager().addTriggerListener(myTriggerListener, keyEquals(triggerKey("myTriggerName", "myTriggerGroup")));
See also this answer.

Related

I'm having a problem with #Scheduled and spring boot. A job after finished happens to run again sometimes after some minutes

I'm having a problem with #Scheduled and spring boot in a job that have to be executed each hour in the day, but the job is being executed when he shouldn't.
For instance... The job has to be executed each hour 00:00:00:000, 01:00:00:000, 02:00:00:000 and so on ... but sometimes, it's not a pattern, happens to be executed again after some minutes for another pod on k8s. Cronjob time is (0 0 * * * ?) every hour.
lock settings
defaultLockAtMostFor = "PT40S",
defaultLockAtLeastFor = "PT20S"
job executation logs
There's a scheduller table in the DB to control the lock, to avoid two pods to execute at the same cronjob time.
anyone knows why this kind of behaviour happens?
Thanks in advance!

Do not fire trigger on app startup if trigger time expired. Quartz

I have a simple trigger which trigger a simple job (let's assume - send an email).
My trigger:
return newTrigger()
.withIdentity(name, group)
.withSchedule(
simpleSchedule()
.withMisfireHandlingInstructionNextWithExistingCount()
)
.startAt(triggerStartTime)
.usingJobData(JobDataMap(triggerData))
.withDescription(description)
.build()
But, imagine that service will not available at triggerStartTime fired time (I just shut down database and my service). Some time later, when I run my service again - in log I see, that the trigger was executed.
UPD #1:
It reproduces when I create simple trigger which should start the next minute, after that I shut down all environments (app+db) and then turn it on during the minute when trigger should fire. Check it:
16:00:00 create trigger which should fire 16:01:00
turn off all environments
wait 16:01:59
turn on and observe that trigger fire
But if I turn on all environments after 16:02:00 it will not fire trigger. It is very strange behavior. Also, I observe, that in this case trigger was not removed from database.
There is a property in quartz to control misfire threshold org.quartz.jobStore.misfireThreshold
The number of milliseconds the scheduler will 'tolerate' a trigger to pass its next-fire-time by, before being considered "misfired". The default value (if you don’t make an entry of this property in your configuration) is 60000 (60 seconds).
Link to configuration document
I think if the exceeded time is below 1 minute(default value), the scheduler still considers that job is pending for normal execution. Try playing with that number.
and this is the actual query fired to get the triggers to be executed, note the second condition in the below query is based on the misfireThreshold property
Link to query

Quartz scheduler incorrect schedule time

I have a spring boot application in which I am trying to schedule a job using quartz scheduler to run daily at a specific time of the day. The following is my code to build the trigger.
DailyTimeIntervalScheduleBuilder scheduleBuilder = DailyTimeIntervalScheduleBuilder
.dailyTimeIntervalSchedule()
.startingDailyAt(TimeOfDay.hourAndMinuteFromDate(activeStartTime))
.endingDailyAfterCount(1)
.withMisfireHandlingInstructionFireAndProceed();
MutableTrigger trigger = scheduleBuilder.build();
The problem I am facing is that the job is scheduled but starting from the next day. So for instance, if I schedule the job for May 22 16:45, then the first fire time for the job is set to May 23 16:45.
I have tried using the builder with withIntervalInHours(24) instead of endingDailyAfterCount(1), but the result is the same.
I am not sure what seems to be the problem.
Note: This behavior is the same regardless of when I schedule my job, i.e., it doesn't matter if I execute this code before or after 16:45, the job is always scheduled for the next day
I am using spring boot version 1.5.10 and spring-boot-starter-quartz version 2.2.5.RELEASE
Can you try below code
CalendarIntervalScheduleBuilder schedule = CalendarIntervalScheduleBuilder
.calendarIntervalSchedule()
.inTimeZone(TimeZone.getDefault())
.withIntervalInDays((int) 1)
.withMisfireHandlingInstructionFireAndProceed();
Trigger trigger = TriggerBuilder
.newTrigger()
.startAt(startDateTime)
.withSchedule(schedule).build();
For the field startDateTime please use current Date time. if you want to start from May 22 16:45 then create the Date object accordingly.
And set the timezone also, or it will pick default system's timezone.

The best way to scheduler a process on the first day every 2 months even the server was down

I have a simple task: I need to run a process on the first day every 2 months even the server was down
If the server will not down – the task is very easy:
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
CronTrigger trigger = new CronTrigger("0 0 1 1 */2 ?");
scheduler.schedule(new Runnable() {
#Override
public void run() {
// do the job
job();
}
}, trigger);
But what if the server was down and I run my job a month ago?
In this case I want to execute my job on the beginning of the next month.
I decided to store in the database when I executed the job last time:
private void job() {
// Store when the job was executed the last time
}
Now, when my server is launched, I need to start the trigger once again, but not immediately.
I can easily calculate when I want to start the trigger, but unfortunately I can not find the appropriate function in ThreadPoolTaskScheduler. There is function that will allow to run task at start time periodically:
public ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period)
Unfortunately, ThreadPoolTaskScheduler does not support
public ScheduledFuture schedule(Runnable task, Date startTime, Trigger trigger)
I implemented the functionality using additional scheduler.execute, but the question if it possible to do it using one schedule.
You could use java.util.Timer to do that, and schdule the next TimerTask inside your TimerTask implementation.
If it has to be exactly two months you should schedule another TimerTask when the TimerTask starts, otherwise you could schedule it when the TimerTask ends.

Placing a Quartz Scheduler in Stand-by Mode

You can place a Quartz scheduler in stand-by mode. During this time all triggers will not fire neither jobs being executed. But what happend if the standby(); command comes up during a job that is in the middle of its execution, let's say it is in the middle of writing a file?
example:
*// start() was previously invoked on the scheduler
scheduler.standby();
// now the scheduler will not fire triggers / execute jobs
// ...
scheduler.start();
// now the scheduler will fire triggers and execute jobs*
I believe calling standby() will only stop further execution of triggers, it will not stop or abort any jobs that are already executing.

Categories