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.
Related
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
I develop a simple Spring Boot app that consumes REST and writes to DB.
I tried a #Scheduled annotation to initiate a task to run it periodically.
But the scheduling process starts automaticly, which is not exactly what I want.
I need an ability to start and stop a scheduled task from a web page.
When a user opens a page he must see a status of a process : Running/Stoped.
What is the easy way to implement it? Create a new thread? How to get a status of a process? Save it in db?
Maybe smb has an example of starting and stoping schedduled task from web page?
Try to use ScheduledExecutorService. For example, first of all create a ScheduledExecutorService:
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
then create a scheduled task:
ScheduledFuture<?> task = scheduledExecutorService.scheduleAtFixedRate(
() -> System.out.println("some task"), 0, 30, TimeUnit.SECONDS);
and when you want to cancel the task, do the following:
task.cancel(true);
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.
I need to execute some task daily. Can I use ScheduledExecutorService for this? Say a piece of code that is running always at particular interval. My doubt I am keeping CPU busy always running my code, but this code will run my actual task once in a day,week or month depends on configuration.
ScheduledExecutorService schedular = Executors.newScheduledThreadPool(1);
schedular.scheduleAtFixedRate(new MySchedular(), 1, 24, TimeUnit.HOUR);
Or do we have any better option?
For very a basic need you can indeed use a ScheduledExecutorService as you do, but if you want to do complex things like scheduling your task at a given hour in the day, you should consider using quartz-scheduler.
Here is how to schedule a task at 10 PM:
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDetail job = JobBuilder.newJob(MySchedular.class)
.withIdentity("job1", "group1")
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger1", "group1")
.withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(22, 00))
.build();
// Tell quartz to schedule the job using our trigger
scheduler.scheduleJob(job, trigger);
// and start it off
scheduler.start();
The same trigger created with a cron expression would be:
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("trigger3", "group1")
.withSchedule(CronScheduleBuilder.cronSchedule("0 22 00 * * ?"))
.build();
Considering that you are using Windows and CronJob is not available, ScheduledExecutorService is a very good choice on your part. The only problem you need to look into is what happens if for whatever reason your process terminates not due to Windows reboot. Usually critical systems have some sort of Watchdog processes that monitor your process and restart it if it was terminated. But this is probably out of scope for this question. In short the answer to your question is: ScheduledExecutorService is the correct choice.
Consider the following sequence of events. Using quartz 1.8.0
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>1.8.0</version>
</dependency>
I schedule a job to be executed in the future
job.setGroup(MY_GROUP);
Date date = scheduler.scheduleJob(job, trigger); // Valid date received
Job executes as expected.
I then try to delete the job by running
boolean unscheduled = scheduler.deleteJob(event.getName(), MY_GROUP); // Always false
Attempt to delete the job always results in **false**
If i let the application to run past the time it was scheduled to execute, after having failed to delete it, it ... does not run (as if it was deleted successfully)
What could explain such a behavior? How can i know what is scheduled in quartz as part of the group?
EDIT:
Trigger is set as:
SimpleTrigger trigger = new SimpleTrigger();
trigger.setStartTime(new Date(event.getStartTime().inMillis()));
trigger.setName("trigger" + event.getTriggerName());
trigger.setRepeatInterval(event.getFrequency());
trigger.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
What trigger are you using? If you haven't specified that the trigger should fire multiple times e.g. on a recurring interval, then it will only fire once and will then be discarded; if your job detail isn't durable then the scheduler will automatically remove it once no more triggers point to it.