开发者

Quartz.NET: Need CronTrigger on an iStatefulJob instance to *delay instead of skip* if running job while schedule matures

开发者 https://www.devze.com 2023-02-01 00:43 出处:网络
Greetings, your friendly neighborhood Quartz.NET n00b is back! I have a Windows Service running iStatefulJob instances on a Quartz.NET CronTrigger based schedule scheme... The CRON String used to sch

Greetings, your friendly neighborhood Quartz.NET n00b is back!

I have a Windows Service running iStatefulJob instances on a Quartz.NET CronTrigger based schedule scheme... The CRON String used to schedule the job: "0 0/1 * * * ? *"

Everything works great. However, if I have a job that is set to run, say, at the X:00 mark of every minute, and that job happens to run for MORE than a minute, I notice that the subsequent job runs IMMEDIATELY after the job is finished executing, rather than waiting until its next scheduled run, effectively "queuing" up instead of merely skipping the job till it's next scheduled run.

I put in the trigger a CronTrigger MisfireInstruction of DONOTHING, but the exact same thing happens when a job overruns its next scheduled execution schedule.

How do I get an iStatefulJob 开发者_StackOverflow中文版instance to merely SKIP a scheduled execution trigger if it is currently running, rather than have it delay it until the first execution completes?

I explicitly set the trigger.MisfireInstruction = MisfireInstruction.CronTrigger.DoNothing;

...But instead of "doing nothing", for a job scheduled to run every minute that takes 90 seconds to complete, I experience the following execution log:

  • Job runs at 9:00:00am, finishes at 9:01:30am <- job runs for 1:30
  • Job runs at 9:01:30am, finishes at 9:03:00am <- subsequent job that should have run at 9:01:00
  • Job runs at 9:04:00am, finishes at 9:05:30am <- shouldn't this one have run at 9:03:00?
  • Job runs at 9:05:30am, finishes at 9:07:00am <- subsequent job that should have run at 9:05:00
  • Job runs at 9:08:00am, finishes at 9:09:30am <- shouldn't this have run at 9:07:00?

... it seems like it runs correctly the first time, on the minute... delays for 30 seconds as the 90 second job execution time expires, and then, instead of waiting till the NEXT full minute, EXECUTES IMMEDIATELY at the 30 second mark... Doubly odd, is that it then finishes the SECOND job on the minute mark, but waits till the NEXT minute mark to execute instead of running it back-2-back...

Pretty much seems like it works correctly EVERY OTHER RUN, when it is not running on the :30 marks...

What's the best way to get a job not to delay/queue, but to just SKIP until it is idle and the next schedule matures?

EDIT: I tried going back to iJobs instead of iStatefulJobs using the same DONOTHING trigger misfire instruction, but the job executes EVERY MINUTE despite the prior execution being still active. I can't seem to get it to skip a scheduled run if it is currently running with either iJob or iStatefulJob...

EDIT#2: I think that my triggers are NEVER misfiring, which is why DoNothing as a misfire instruction is useless... Given that's the case, I guess I need another mechanism to detect if a job instance of a schedule is running to ensure the job SKIPS its next execution until its following scheduled time rather than delaying it until first instance completion...

EDIT3: I tried adding an element to the iStatefulJob jobdatamap called "IsRunning"... I set it to TRUE when the execute sequence starts, and then return it to false after job completion. Before executing, it checks the element, which is apparently persisted between jobs, and prematurely quits the execution (logging "JOB SKIPPED!") if it detects it to be true... This unfortunately doesn't work, for probably obvious reasons: If the jobs are running following the bulleted schedule above, then the job is never SIMULTANEOUSLY running along with itself, as it is delaying the run till the job ends, so this check is useless. According to documentation, returning to iJob from iStatefulJob would not help here as the jobdatamap is only persisted between jobs in the Stateful job type...

I still haven't solved how to SKIP a scheduled job instead of delaying it till it's current iteration completes... If anyone has ideas, you're a lifesaver! :)


It should be caused by misfireThreshold of RAMJobStore (http://quartznet.sourceforge.net/apidoc/topic2722.html).

The time span by which a trigger must have missed its next-fire-time, in order for it to be considered "misfired" and thus have its misfire instruction applied.

It is 60 seconds by default. So job isn't considered as "misfired" until it is late for more than misfiredThreshold value.

To resolve the problem just decrease this threshold (below code sets to 1 ms):

...   
properties["quartz.jobStore.misfireThreshold"] = "1";
...
schedulerFactory = new StdSchedulerFactory(properties);

It should resolve the issue.

0

精彩评论

暂无评论...
验证码 换一张
取 消