Does the quartz scheduler delete triggers? - java

I basically want to know, if the scheduler itself deletes triggers after they have fired if there are not any other points in time where they would ever fire again?
I need to know this so that I know how to tidy up after a job has been executed.
I have already read through many posts about triggers and jobs. I have also read through all the official quartz lessons. Only thing I found out there was that jobs can be deleted if you set their property "durable" to false when there are no more triggers pointing to it.. That is also how my question came up on how or when the scheduler deletes its triggers

Yes, it automatically removes these triggers.
I've found some documentation for this topic: https://www.quartz-scheduler.org/api/2.1.7/org/quartz/SimpleTrigger.html
there is a line stating:
int getRepeatCount()
Get the the number of times the SimpleTrigger should repeat, after which it will be automatically deleted.

Related

is it possible to restart a job after stopping?

I am working on a project in which I can hit maximum 15k hit a day to Google API. So I want to stop the job after 15k and resume it next day. Please let me know how can I do the same.
Please let me know how can I achieve the same. Right now I am thinking of using quartz scheduler to schedule the job every day.
If anyone needs full explanation, I can explain it more.
Thanks in advance.
You can stop a step execution (and its surrounding job) using StepExecution#setTerminateOnly. So in your case, you can use for example a ItemReadListener#afterRead or ItemWriteListener#afterWrite that has access to the step execution and set the terminateOnly flag after processing 15k items. When you stop the job gracefully like this, its status will be STOPPED and you will be able to restart it again the next day as you mentioned.
You can find an example in the Stopping a Job Manually for Business Reasons section of the reference documentation.
Hope this helps.
I had something similar where I needed to stop a 24/7 job 5 minutes before server maintenance was scheduled to start.
The easiest I found was to use the Reader and return null to indicate the job should stop. In your case, return null when 15k API requests were processed.
This will likely mean you'll need a bean (could be just an AtomicInteger) available to the Reader and updated by the Processor. But also a Job Listener (sorry, I don't have the code) which also knows about the bean. If the maximum is reached the Listener sets up a custom job exit value to be returned to the scheduler when the job stops. The scheduler has to be configurable enough to know the particular exit value means to start the job again the next day. (Any other non-zero value was treated as an error.)
This means there is a small possibility the job hits 15k but also that it is the last item, so the job is scheduled again for the next day even though there is nothing more to be processed. It shouldn't matter though - the job will start the next day and stop immediately with a normal complete status so the scheduler will not schedule again.

Quartz How do I put triggers in a state where they wont re-fire a misfire

I have an interesting issue with our web application. We recently had a huge concurrency problem with Quartz firing off the same java class in hundreds of threads at once causing contention on the database and completely locking our application. Before we were able to address the underlying issue, I had to set all misfire_instr to "1" (Do not re-fire a misfire) on the database table qrtz_triggers to get the application to come up and serve normal traffic. We then manually fired off the missed schedules slowly to avoid the concurrency issue.
I have fixed the concurrency issue and am ready to hot-deploy our application, but am afraid if I set the misfire_instr back to 2 (re-fire misfires), the missed schedules will re-fire again based on prev_fire_time?
Proposed solution - set prev_fire_time to a couple minutes before the next_fire_time so it thinks the last schedules went off. Is my assumption here correct that a schedule is considered missed if the prev_fire_time is before the last time represented by the cron expression?
I also see that schedules which have yet to run have -1 in the column, is this the default for a new schedule, perhaps I should be using this value instead?
Since we needed this to go in immediately, I decided to just try my luck with using -1 as the prev_fire_time value (and updating the triggers back to 2). This worked as expected.

How to save Quartz executed jobs?

One problem, after executed jobs, quartz delete jobs from database qrtz_triggers table, but in specific situation needed to repeat job which is failed.
Is any configuration options or way to store jobs to another table after execute???
Thanks
If you are using JDBCJobStore, your jobs are stored in a table like QRTZ_JOB_DETAILS, and your simple triggers are stored in QRTZ_SIMPLE_TRIGGERS, your cron trigers are stored in QRTZ_CRON_TRIGGERS, and all the triggers are stored in QRTZ_TRIGGERS.
If you expect your job is durable and remains when no triggers are associated to the job, you should call storeDurably(true) when building your JobDetail. For example:
JobDetail jobDetail = JobBuilder.newJob()
.ofType(DataMapJob.class)
.withIdentity("dataJob", "dataJobGroup")
.storeDurably(true)
.requestRecovery(true)
.build();
Hope it helps.
This is exactly what the durable flag is for. Durable jobs remain registered in Quartz even if there are no triggers associated with the job. On the other hand, non-durable jobs are automatically deleted by Quartz where there are no associated triggers (e.g. after all associated triggers fired and have been deleted by Quartz).
For details, you can refer to JobDetailImpl javadoc.

Is there a way to simulate a trigger misfire in Quartz? (Java)

I'm looking for a way to simulate or force a trigger misfire programatically. Here's the scenario:
I have a job set to trigger but the job requires some underlying resource that may be unavailable at times. If the resource is unavailable, I would like Quartz to re-fire the trigger later based on the misfire policy.
I've explored two options that are similar but not quite what I'm looking for:
Throwing a JobExecutionException with refireImmediately set to true:
Works, but doesn't delay execution based on misfire policy; this
would hammer the resource availability check.
Scheduling a second trigger at some fixed interval of time in the
future: Also works, but doesn't take into account misfire policy.
This means a job could wind up with a bunch of retries queued up
stemming from different failed runs.
Any ideas or anything I'm missing? Thanks!
If I got it right, you don't need to force or simulate a misfire because the resource availability is "something your Job can handle".
Misfires exists and are managed by Quartz for situations like server shutdown or other "unexpected problems" that prevent Job execution.
You have two options to follow to implement a simple fault-tolerance retry logic;
your Job can execute it's logic only when the underlying resource is available, so you can:
Wait for the resource to become availabile:
in this case your job waits and repeat the check for the resource availability, eventually after a short timeout, the job can give up and end.
Just do nothing if the resource is not available:
in this case the job ends without doing anything and the it will fire normally and retry according the Trigger definition.
In both cases, if the resource is avaliable, the Job can execute it's inner logic and use the underlying resource. (No misfires, because the Job was actually executed)
This can be done using a Trigger, setting the misfire policy you need in case the Job cannot be executed at all. See This great and detailed article on Quartz misfires.
In your situation, If you want to execute a job one time every day:
Define a Cron trigger that fires multiple times in a day in a given span of time, for exemple, every 15 minutes from 8:00 AM to 12:00 AM:
0 0/15 8-12 * * ?
Buld a Job that use one of the two approaches described before
The first time your Job inner logic executes (that is, the resource is available) your job will save a "job executed flag" with the day of execution somewhere on DB.
On the following trigger executions, the Job will check the flag and will not execute it's inner logic again.
Also, if your job will take long time to finish, you may want to prevent concurrent execution of the same job using the following annotation on the job implementation:
#DisableConcurrentExecution
See Quartz tutorials for more informations on job execution.

execute job immediately

I try to run emergency job immediately after scheduled with quartz.
my code is below.I give current time as startTime.
Bıt it takes 30- 40 seconds to run job after schedule.How can run immediately.
// Trigger the job to run now, and then repeat every 40 seconds
jobTrigger= newTrigger()
.withIdentity(Long.toString(emergencyJob.getId()), Long.toString(emergencyJob.getVariant().getId()))
.withPriority(emergencyJob.getPriority())
.startAt(new Date(ctime))
.withSchedule(simpleSchedule().withMisfireHandlingInstructionFireNow()
)
.build();
scheduler.scheduleJob(jobDetail, jobTrigger);
You can also fire it with:
scheduler.triggerJob(jobDetail.getKey());
This is just a guess (it's been a while since I've used quartz), but since you create the Date instance before you actually call build(), it may not be able to meet that time constraint and simply fires 40 seconds later when the next scheduled trigger fires. Try something like this to confirm:
.startAt(new Date(System.currentTimeMillis() + 1000))
Play with the 1000ms value to suit your needs. This is to give it a bit more time to meet the first scheduled trigger.
Probably bit late, but maybe someone will find this useful. I had same issue with quartz on JBoss AS (triggers executed late - approximately 20-30 seconds, for no obvious reason). I came to conclusion that this is caused by some bug in JBoss. Same application worked fine on glassfish. I have changed only PU in order to work with eclipse link and other persistence worked fine on JBoss, so I don't suppose issue there. This behaviour occured only when using quartz database task store, with RAM store it worked fine.
To answear the question. If you use database taskstore, consider changing it to RAM store for me that caused triggers to be fired at time.

Categories