crazydiv
crazydiv

Reputation: 842

Quartz: Debug undesired multiple job runs

The job is being scheduled at Application_Start() :

var y= JobBuilder.Create<YY>()
            .WithIdentity("YY")
            .Build();

ITrigger z= TriggerBuilder.Create()
            .WithDescription("Runs.")
            .WithDailyTimeIntervalSchedule(x => x
            .WithIntervalInHours(24)
            .OnEveryDay()
            .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(9, 30))
            .InTimeZone(TimeZoneInfo.Utc))
            .Build();

Scheduler.ScheduleJob(y, z);

Within the job, I am Logging "Job Started" at the beginning. The job was running normally for past couple of days but since past 2 days, I am able to see "Job started" occuring 3 times in the logs, with a few milliseconds difference. The same is happening with the notification mailer which is added to the job.

I suspect it is due to misfire instructions, but is there any approach of debugging and identifying the cause of the issue, and also to make sure that only 1 instance of job gets executed.

This job takes 1-1.5hrs for execution, and it is possible that a server restart and deployment happened while the job was triggering. Could that have affected the triggering scenario.

Upvotes: 1

Views: 1653

Answers (2)

M C
M C

Reputation: 626

Define your Job that way:

[DisallowConcurrentExecution]
public class YourJobClass : IJob
{
    //  Your Code...
}

The [DisallowConcurrentExecution] Attribute makes sure there's max one instance of the job at any time.

It's just a guess but maybe following code can help, if your problem is caused by misfires:

You can change properties of the scheduler with following code:

IScheduler scheduler;        
ISchedulerFactory schedulerFactory;
NameValueCollection propColl = new NameValueCollection();

propColl.Add("org.quartz.jobStore.misfireThreshold", "216000000");  // Amount of milliseconds that may pass till a trigger that couldn't start in time counts as misfired (216000000 ms => 1 hour) 
propColl.Add("org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow", "5"); // Trigger may fire up to 5 ms before scheduled starttime
propColl.Add("quartz.threadPool.threadCount", "1"); // Allows only one Thread in parallel
schedulerFactory = new StdSchedulerFactory(propColl);
scheduler = schedulerFactory.GetScheduler();
scheduler.Start();

As for your Question regarding debugging this issue: I personally only know the trial and error method. Change a little thing and see what happens.

Upvotes: 2

Nzall
Nzall

Reputation: 3565

While it does not directly solve the problem that multiple jobs run at the same time, there are ways to prevent or at least mitigate multiple jobs running at the same time.

Scheduler has a method checkExists() that can accept a jobKey or a triggerKey and returns true if the job or the trigger already exist.

Please note that due to the proximity of these jobs, there might be a race condition that could in rare cases still cause double job execution.

Upvotes: 0

Related Questions