JAVA Quartz - Skip job if previous is still running AND wait for the next schedule time - quartz-scheduler

I have a Java solution that uses Quartz 2.2.3, and what I have is:
My job class is annotated #DisallowConcurrentExecution to avoid concurrence, so the same job just can run once per time (OK)
It is a CRON and runs every 1 hour (OK)
The time is 1pm and the the job starts run (OK)
Now the time is 2pm and the previous job didn't finish yet (OK)
As the class is annotated the next job will not start (IT IS GREAT - OK)
Now the time is 2h:15min and the first job just finished (OK)
Now the issue, as the second job didn't start at 2pm BUT now the first just finished, the second one will start.
This is my problem, I don't want to make the second job wait if the previous didn't finish, I want to skip the second one and when the time turns 3pm the job can run. Reading javadoc I added the withMisfireHandlingInstructionDoNothing() but it didn't work.
I think I'm doing something wrong or missing something.
My code:
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDetail job = JobBuilder.newJob(TestCronService.class).withIdentity("testA","testB").build();
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("testA","testB")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 * * * ?")
.withMisfireHandlingInstructionDoNothing())
.build();
scheduler.scheduleJob(job, trigger);
scheduler.start();

Change the function :
withMisfireHandlingInstructionDoNothing()
with
withMisfireHandlingInstructionNextWithRemainingCount()

Related

How to configure workflow runtime (Informatica)?

I would like the workflow to run for 20 minutes....If the running process does not complete within 20 minutes, the workflow should be ended immediately..However, I can only find the timer, but it is used for starting the process after the indicated time which is not I'm looking for...Does anyone know how to specify the duration for the workflow?
[updated to cover complete scenario and cover issues raised by Koushik Sinharoy in comments]
You can achieve it using the timer:
Link one to the Start task and set it to run for 20 minutes in
parallel with your session.
Have a Decision task with Treat the input links as set to OR. This will trigger the decision whenever any of the preceeding task ends, so either your session will get completed or timer runs out (whatever happens first).
Set the Decision condition to $s_your_session.Status = SUCCEEDED.
Link the Decision task to Control Task.
Set Control task to Fail parent.
Add a condition $Decision.Condition = False to the link between Decision task and Control task.
This should be the result:
Start--->s_your_session--\
\ > Decision [OR] ---(False)---> Control Task [Fail parent]
\-->timer-----------/
Thanks Koushik Sinharoy for the remarks below!

Play Framework - Schedule a task at precise time [duplicate]

This question already has answers here:
scala - How to run a task every day a 11PM
(2 answers)
Closed 6 years ago.
I'm doing a Scala - Play application and I want to schedule a task to sending mail everyday at 3 A.M, so I create a class for that but i'ts not working:
class ManageSendInvalidateDaemon #Inject() (app: Application, emailSender: EmailSender, mailer: MailerClient) {
Akka.system(app).scheduler.schedule(
scala.concurrent.duration.Duration.create(20,TimeUnit.SECONDS),
scala.concurrent.duration.Duration.create(60, TimeUnit.SECONDS),
new Runnable(){
override def run()={
//Function to send the mail
}
}
);
};
I think the problem is here:
scala.concurrent.duration.Duration.create(20,TimeUnit.SECONDS),
scala.concurrent.duration.Duration.create(60, TimeUnit.SECONDS),
I don't really understand what it's the use of these 2 lines
That will not work as you expect. Akka scheduler just lets you specify the recurrency of the task, but not the day, hour etc when it will run (ex: you can tell it to run a task every 10 minutes, but not run this at 15:30 each Monday).
Those two lines instruct Akka to run that task every 60 seconds, and run the first time 20 seconds after you define it (so if the schedule call is executed at 12h30m that task will run the first time at 12:30:20 and then 12:31:20, 12:32:20, etc).
To overcome this, you just need to run a task periodically (in your case, each minute for example), and check the current hour. If it is 3AM send those emails (and eventually store anywere that this task was executed).
Another option is to use something like akka-quartz-scheduler, that lets you specify that type of scheduling
I had the same problem. So I created a method to calculate how much time from now until the time I want to run my
schedule = Akka.system().scheduler().schedule(
Duration.create(nextRunTime(), TimeUnit.MILLISECONDS),
Duration.create(DAY_IN_MS, TimeUnit.MILLISECONDS),
...,);
The nextRunTime() method calculates how much time in milliseconds will be until the next 3 AM and after that I set an interval of one day (DAY_IN_MS)
private int nextRunTime() {
String runTimeValue = "03:00";
LocalTime now = new LocalTime();
LocalTime runTime = new LocalTime(runTimeValue);
int timeUntilRun;
if (runTime.isAfter(now)) { // From now until the run time
timeUntilRun = runTime.getMillisOfDay() - now.getMillisOfDay();
} else { // From now until midnight, plus from midnight until the run time
timeUntilRun = DAY_IN_MS - now.getMillisOfDay() + runTime.getMillisOfDay();
}
Logger.info("nextRunTime(): next run in " + timeUntilRun + " ms");
return timeUntilRun;
}

How does DeltaSpike #Schedule wait finish before a new execution?

I am using this lib DeltaSpike Schedule to create cron tasks.
My task runs every minute, but I do not know how set Schedule to wait complete the old task.
#Scheduled(cronExpression = "0 * * * * ?")
public class WaiterRideTask implements Job {
}
If a task delays more than 1 minute, then other task is created yet.
Thanks Dar Whi. This solved my problem: #DisallowConcurrentExecution

quartz trigger builder startnow not firing the trigger during the start

i am tring to use quartz builder for creating a cron trigger and trying to give the startnow instruction. but the trigger is not starting instead it is starting only after completing the given time interval. can someone help me to start the trigger during the starting the server.i am using plain quartz and no springs.
Trigger trigger = newTrigger()
.withIdentity(SchedulerConstants.TRIGGER_CLARITY,SchedulerConstants.QI_GROUP)
.withSchedule(cronSchedule("0 0/60 * * * ?").withMisfireHandlingInstructionDoNothing())
.startNow()
.build();
There wont be any effect of calling startNow() on a CronTrigger as it triggers the job based on cron expression supplied unlike time based SimpleTrigger.
Your cron expression tells Quartz to run every 60 mins starting 0th minute of ever hour.
Unless you start the scheduler at exactly 0th min, you willnot see startNow effect.
Hope this is clear to you.
Refer Quartz CronTrigger tutorials/documentation for more details.
You can add a second trigger to your job with StartNow. I think this would work for you assuming you had a job class called SomeJob.
var schedulerFactory = new StdSchedulerFactory();
var scheduler = schedulerFactory.GetScheduler();
scheduler.Start();
IJobDetail job = JobBuilder.Create<SomeJob>()
.WithIdentity("job1", SchedulerConstants.QI_GROUP)
.Build();
Trigger trigger = newTrigger()
.withIdentity(SchedulerConstants.TRIGGER_CLARITY,SchedulerConstants.QI_GROUP)
.withSchedule(cronSchedule("0 0/60 * * * ?").withMisfireHandlingInstructionDoNothing())
.build();
scheduler.ScheduleJob(job, trigger);
IJobDetail job2 = JobBuilder.Create<SomeJob>()
.WithIdentity("job2", SchedulerConstants.QI_GROUP)
.Build();
Trigger trigger2 = newTrigger()
.withIdentity("trigger2",SchedulerConstants.QI_GROUP)
.StartNow()
.build();
scheduler.ScheduleJob(job2, trigger2);
.startNow() will let the trigger startup, but the trigger may or may not fire at this time - depending upon the schedule configured for the Trigger.
you can trigger the task when application starts
_scheduler.TriggerJob(new JobKey("A/BTestConfigsDaily")).Wait();

Quartz.Net - delay a simple trigger to start

I have a few jobs setup in Quartz to run at set intervals. The problem is though that when the service starts it tries to start all the jobs at once... is there a way to add a delay to each job using the .xml config?
Here are 2 job trigger examples:
<simple>
<name>ProductSaleInTrigger</name>
<group>Jobs</group>
<description>Triggers the ProductSaleIn job</description>
<misfire-instruction>SmartPolicy</misfire-instruction>
<volatile>false</volatile>
<job-name>ProductSaleIn</job-name>
<job-group>Jobs</job-group>
<repeat-count>RepeatIndefinitely</repeat-count>
<repeat-interval>86400000</repeat-interval>
</simple>
<simple>
<name>CustomersOutTrigger</name>
<group>Jobs</group>
<description>Triggers the CustomersOut job</description>
<misfire-instruction>SmartPolicy</misfire-instruction>
<volatile>false</volatile>
<job-name>CustomersOut</job-name>
<job-group>Jobs</job-group>
<repeat-count>RepeatIndefinitely</repeat-count>
<repeat-interval>43200000</repeat-interval>
</simple>
As you see there are 2 triggers, the first repeats every day, the next repeats twice a day.
My issue is that I want either the first or second job to start a few minutes after the other... (because they are both in the end, accessing the same API and I don't want to overload the request)
Is there a repeat-delay or priority property? I can't find any documentation saying so..
I know you are doing this via XML but in code you can set the StartTimeUtc to delay say 30 seconds like this...
trigger.StartTimeUtc = DateTime.UtcNow.AddSeconds(30);
This isn't exactly a perfect answer for your XML file - but via code you can use the StartAt extension method when building your trigger.
/* calculate the next time you want your job to run - in this case top of the next hour */
var hourFromNow = DateTime.UtcNow.AddHours(1);
var topOfNextHour = new DateTime(hourFromNow.Year, hourFromNow.Month, hourFromNow.Day, hourFromNow.Hour, 0, 0);
/* build your trigger and call 'StartAt' */
TriggerBuilder.Create().WithIdentity("Delayed Job").WithSimpleSchedule(x => x.WithIntervalInSeconds(60).RepeatForever()).StartAt(new DateTimeOffset(topOfNextHour))
You've probably already seen this by now, but it's possible to chain jobs, though it's not supported out of the box.
http://quartznet.sourceforge.net/faq.html#howtochainjobs