In quartz scheduler I have a doubt
For example
If we schedule job for every 5 minutes or 10 minutes or 2 hours it is ok we call scheduler using regular time interval like below no problem,
SimpleTrigger simpleTrigger = new SimpleTrigger("mytrigger",sched.DEFAULT_GROUP,new Date(),null,SimpleTrigger.REPEAT_INDEFINITELY,30L*5000L);
But,If I schedule job # 2'0 clock and 3'0 clock today then,tommorow I change it to 5'0 clock and 7'0 clock and 11'0 clock, my doubt is if fixed interval we call it in above way but it not fixed or periodic interval how do we handle it. Any suggestions or Ideas or examples regarding my query....
What you can do is define the intervals in a file or DB and read it from there.
Also define a JobListener.
Store the interval values in the JobDataMap and every time the job starts, use the listeners method jobToBeExecuted() and read the values from the file/DB and compare it with the values in the JobDataMap.
If they are the same, then no update was done and the job runs, if it was changed, reschedule the job using Scheduler.rescheduleJob(TriggerKey triggerKey,Trigger newTrigger).
Note that there is a little problem with this method, the configuration will only change once the job runs, so even though you update the file/DB the next run would still be in the old time, and only the run after that would be in the new time.
Related
I have a non-concurrent quartz job running on 6 application server instances. A high level responsibility of the job is to walk through a DB table and process and update which ever row is expired. Now I see a behavior of the job which is not understandable.
I have a configuration by which the job should be triggered after 15 minutes, but as the span of a single run can be multiple days, each of this trigger after 15 minutes should be suppressed by a lock already acquired by running job instance.
So, the ideal behavior is, job starts running on one of the 6 server instances, it completes a single DB table iteration in let us say 3 days. Meanwhile, quartz is trying to push in another job every minutes, but as lock is already acquired, it should not. After 3 days when the first job run finishes quartz scheduler should succeed in starting another job, within <= 15 minutes of the first run endtime.
But, in reality I see a behavior, where the the job has run for some days and has not run for some of the days. some time this gap is as long as 8-10 days. I am unable to explain this scenario.
The closest theory I can think of, is that it might be the case that during a particular job run, the server instance got killed(due to deployment/redeployment), because of which the quartz did not get a chance to remove shared lock. So, all the attempts of acquiring a lock for next job run keep on failing till the orphan lock is not expired by an expiry date. The moment it got expired, a new job kicks in.
My question here is, what could be the possible explanations to this, and more importantly, how to debug it? Any leads to Quartz Lock management documentation for non-concurrent jobs can helpful.
I use DisallowConcurrentExecution annotation for non-concurrency.
In my system, user can create a schedule with time and conditions. Before 30 mins of schedule time, if the conditions are not satisfied the system will raise an alarm to notice users about that.
My system are spring boot applications and using spring scheduled task to trigger alarms. The problems is when user creates a lot of schedule in the future, if I create a scheduled task for each schedule data, there will be memory problem.
My current solution is a create a schedule run at a time of everyday to scan all data in next 24 hours and create scheduled task for them to trigger alarm. This will reduce scheduled tasks created but if user creates new schedule data in next 24 hours after scanning, that data will be not trigger any alarm.
So what should I do?
Is there a reason that you are scheduling all of this in JVM memory? If the JVM crashes (or is simply rebooted), the timers would then be lost as if the user never scheduled any alarm. As you mentioned, creating a timer per request would likely not be a scalable solution.
Without knowing the specific details of your system, the most common approach would be to persist (i.e. in a DB, flat file, etc.) the data each time a user requests to schedule event. This way, in the event of a crash or reboot, you won't lose events. Similarly, this approach can scale to multiple servers if necessary. Then, at whatever granularity you support (i.e. minute, hour, day, etc.) there would be a process or thread (only a single monitor thread) find all of the events which have expired since you last ran. Finally, once this thread has identified events that need an "alarm," this one thread can control sending these events for active processing. This thread can either individually handle each event or otherwise submit them to an active work queue for parallelization.
More specifically, if you have alarms which could go off at any minute, you should schedule a monitor thread to run every minute. This thread should find all the events which require an alarm and then actually send that alarm.
Remember that how often you should schedule your monitor thread is a function of the resolution you want for your alarms and your tolerance for late alarms. If late alarms are totally unacceptable, then your monitor must run at least as often as the finest granularity for scheduling an alarm event. This is, of course, assuming alarms are always scheduled in the future-- otherwise, you will probably want to double the frequency of your monitoring checks. To see why, consider the following example:
minute 0: Run monitor
minute 0: User schedules alarm for minute 0
minute 1: Run monitor
If we run the monitor once per minute but allow the user to schedule an alarm in the current minute, it's quite possible that we'll miss the event (as shown in the example above). I can go into this more deeply if necessary, but this is here mostly for completeness as I have no indications from your description that this will actually pose any problems.
Good luck.
I am wondering if there is a function/method to create jobs which are triggered on random time. By that I mean that if I set a cron schedule to be triggered every monday at 10.00 am and given a time interval, lets say 30 minutes, the trigger will always go off from 9.30 ~ 10.30.
For example this is the cron schedule.
schedule.setCronSchedule("0 0 10 ? * MON");
trigger = newTrigger()
.withIdentity(triggerId)
.startNow() // <~~~~~~~~~~~~~~~ ???
.withDescription(schedule.getCronSchedule())
.withSchedule(cronSchedule(schedule.getCronSchedule())).build();
If I have a variable with a specific range in minutes can I set it to trigger randomly? And by that I mean not just take the cron schedule string and remodify it, but using a method to trigger the event every time, based on the random range so first monday may be triggered at 10.01 second monday may be triggered at 9.46 and etc.
Thanks in advance.
To fire a schedule at some time between 1.00am and 1.30am every day, you could try this:
schedule.setCronSchedule(String.format("0 %d 1am * * ?", random.nextInt(30)));
Unfortunately there isn't anything built into Quartz, or even unix cron for that matter. And the randomness is going to be the same every day from here on, unless you regularly reset the schedule. But perhaps that isn't a problem for your situation.
Suppose I have a spring job run every 5 minute, usually the job will take about one minute to complete, but if something goes wrong the job will last more than 5 minute. Before last job finished , another job will start. So, the two jobs will interfere with each other?
ps: I use the spring schedule annotation to schedule jobs.
You can control this behavior. If you want to leave a fixed amount of time between the end of one job and the start of the next, use the fixedDelay http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/annotation/Scheduled.html#fixedDelay--.
If you use the fixedRate, then jobs may overlap. Whether that's "ok" depends on what your job does. But you can prevent this from happening with fixedDelay if you want.
hello there is something i've realized with quartz when working.Say a cron is set to wake up every 2min with the expression 0 0/2 * * * ? .
When you run the project at say 13:10:30, the first action happens at 13:12:00 and the second 13:14:00 and every 2min 0 second for the rest. Obviously between the startup of the project and the first occurence of the action there have been 1mn:30s only.
Is there a way to for the first occurrence to respect the 2min no matter which at seconds the project starts?
Cron jobs are configured in Quartz using the CronTrigger class. The alternative is to use SimpleTrigger, which you can construct using fixed delay intervals. SimpleTrigger has various constructors, allowing you to specify the start time, end time, number of repeats, repeat interval, and so on.
Having said that, I'd recommend against using Quartz for this kind of scheduling, and use java.util.concurrent.Executors.newScheduledThreadPool(). It's much easier than Quartz when it comes to simple repeating tasks.
Quartz may use cron for the scheduling, which is based on date and time, not duration. This means that the cron expression you define is directly related to the current time on the machine, not on when the application started.
I am not aware of a Quartz configuration that will help you to solve your problem. However, a solution is to create your own Thread, which started during the launch of your application and that basically waits 2 minutes before calling a method:
while (running) {
Thread.sleep(1000 * 120);
doStuff();
}