Variable interval in Quartz.net - c#

Does anyone know is it possible to schedule a job in Quartz.net with variable interval?
For example, I have an interval 10 to 20 and I need to schedule a job, which would be executed every n seconds, where n is random number between 10 and 20 refreshed after each job execution.
Thanks.

Build your trigger for first fire in this way:
var triggerKey = new TriggerKey("simpleTrigger", "simpleTriggerGroup");
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity(triggerKey)
.StartNow()
.Build();
Then, in the Execute method of your job class modify the trigger:
public void Execute(IJobExecutionContext context)
{
Console.WriteLine(string.Format("{0} hello this is a test", DateTime.Now.ToString("r")));
var newInterval = new Random().Next(20, 30);
// retrieve the trigger
var oldTrigger = context.Scheduler.GetTrigger(new TriggerKey("simpleTrigger", "simpleTriggerGroup"));
// obtain a builder that would produce the trigger
var tb = oldTrigger.GetTriggerBuilder();
// update the schedule associated with the builder, and build the new trigger
var newTrigger = tb.StartAt(DateTime.Now.AddSeconds(newInterval)).Build();
context.Scheduler.RescheduleJob(oldTrigger.Key, newTrigger);
Console.WriteLine("Trigger fired... changed interval to {0}", newInterval);
}
The job will be executed in different intervals.

Related

Configuring quartz.net scheduler in .net

I have an application in .Net framework and I'm using quartz scheduler. I need to configure quartz.
Now I have one method which is fired every 15 minutes. These method is used to do some work with database. I want, in case, that work of procedure is complete, then start waiting period and after that period again start these database method.
For procedure there will be maximum time which cannot be longer. For examplpe 60 minutes. Do you have any ideas how to configure length of working procedure, how to stop when work is finished and how to define waiting time between?
// configure Quartz
var stdSchedulerProperties = new NameValueCollection
{
{ "quartz.threadPool.threadCount", "10" },
{ "quartz.jobStore.misfireThreshold", "60000" }
};
var stdSchedulerFactory = new StdSchedulerFactory(stdSchedulerProperties);
var scheduler = stdSchedulerFactory.GetScheduler().Result;
scheduler.Start();
// create job and specify timeout
IJobDetail job = JobBuilder.Create<JobWithTimeout>()
.WithIdentity("job1", "group1")
.UsingJobData("timeoutInMinutes", 60)
.Build();
// create trigger and specify repeat interval
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithSimpleSchedule(x => x.WithIntervalInMinutes(15).RepeatForever())
.Build();
// schedule job
scheduler.ScheduleJob(job, trigger).Wait();
/// <summary>
/// Implementation of IJob. Represents the wrapper job for a task with timeout
/// </summary>
public class JobWithTimeout : IJob
{
public Task Execute(IJobExecutionContext context)
{
return Task.Run(() => Execute(context));
}
public void Execute(IJobExecutionContext context)
{
Thread workerThread = new Thread(DoWork);
workerThread.Start();
context.JobDetail.JobDataMap.TryGetValue("timeoutInMinutes", out object timeoutInMinutes);
TimeSpan timeout = TimeSpan.FromMinutes((int)timeoutInMinutes);
bool finished = workerThread.Join(timeout);
if (!finished) workerThread.Abort();
}
public void DoWork()
{
// do stuff
}
}

Misfired Simple triggers are executing Jobs in spite of Setting misfire policy to "IGNORE"

I am using Quartz in .Net.
Irrespective of "quartz.jobStore.misfireThreshold" i set and setting misfire policy to ignore, still i see job getting executed.
Ideally this should never happen.
I have initialized both JobListener and Trigger listeners for the same
Here is my snippet
var props = new NameValueCollection
{
{ "quartz.serializer.type", "binary" },
{"quartz.threadPool.threadCount","1" },
{"quartz.jobStore.misfireThreshold","3000" }
};
var schedulerFactory = new StdSchedulerFactory(props);
// get a scheduler
var scheduler = await schedulerFactory.GetScheduler();
//scheduler.CheckExists()
await scheduler.Start();
var job3 = JobBuilder.Create<HelloJob>()
.WithIdentity("myJob3", "group3")
.UsingJobData("jobSays", "Hello World 333333")
.UsingJobData("myFloatValue", 9.423f)
.Build();
var trigger3 = TriggerBuilder.Create()
.WithIdentity("trigger3", "group3")
.WithSimpleSchedule(x => x
.WithMisfireHandlingInstructionIgnoreMisfires())
.StartAt(DateTimeOffset.UtcNow)
.Build();
await scheduler.ScheduleJob(job3, trigger3);
.WithMisfireHandlingInstructionIgnoreMisfires() fires all triggers that were missed as soon as possible and then goes back to ordinary schedule. You should use .WithMisfireHandlingInstructionDoNothing(), trigger with explicitly set "MISFIRE_INSTRUCTION_DO_NOTHING" misfire instruction handler, meaning that all misfired executions are discarded, it simply waits for next scheduled time. A misfire occurs if a trigger "misses" its firing time because there are no available threads in Quartz’s thread pool for executing the job

Update Quartz.net cron trigger not to execute on a particular date/dates for daily trigger.

I have cron trigger which fire daily at particular time of the day, I have to update that trigger so that i don't want that trigger to be executes on particular date.
eg. I have trigger which execute daily on each day, I have to pass a date (31Oct2017) On this date this trigger should not execute.
I tried below code
var calendar = SCSScheduler.Scheduler.GetCalendar(id);
CronCalendar cronCal = new CronCalendar(calendar,cronExceptionSchedule);
SCSScheduler.Scheduler.AddCalendar(id, cronCal, true, true);
var newTrigger = tb.WithCronSchedule(cronSchedule)
.StartAt(DateTime.UtcNow)
.ForJob(id)
.ModifiedByCalendar(id)
.Build();
SCSScheduler.Scheduler.RescheduleJob(key, newTrigger);
I do not find any method to update calendar to not to execute job for this particular date.
You should use the HolidayCalendar class, which is used to exclude whole days from the triggers you create.
This is actually quite well described in the documentation (code for quartz 3.0beta1):
HolidayCalendar cal = new HolidayCalendar();
cal.AddExcludedDate(new DateTime(2017, 10, 31));
await sched.AddCalendar("myHolidays", cal, false, false);
ITrigger t = TriggerBuilder.Create()
.WithIdentity("myTrigger")
.ForJob("myJob")
.WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(9, 30)) // execute job daily at 9:30
.ModifiedByCalendar("myHolidays") // but not on holidays
.Build();

Quartz.Net daily interval schedule

does anyone know if the following is possible with a cron schedule or another schedule type ?
Interval in Minutes 5
Daily between 1h30 and 23h00
Every second day
I tried DailyIntervalSchedule which comes close but without the every second day clause. I tried cron as well but failed because of the daily interval between 1h30 and 23h00.
Any help is really apreciated.
Thanks T4E
I hope that the method I'm describing now may help you. You should define two triggers. These triggers should schedule with same job.
// construct a scheduler factory
IScheduler sched = StdSchedulerFactory.GetDefaultScheduler();
// define the job and tie it to our HelloJob class
IJobDetail job = JobBuilder.Create<HelloJob>().StoreDurably()
.WithIdentity("myJob", "group1") // name "myJob", group "group1"
.Build();
sched.AddJob(job,true);
string cron = "0 0/5 2-23 1/2 * ?"; // interval in minutes 5 2h00 and 23h00 every second day
string cron1 = "0 30,35,40,45,50,55 1 1/2 * ?"; // 1h30 every second day
// Trigger the job to run now, and then every 40 seconds
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger", "group1")
.StartNow()
.WithCronSchedule(cron)
.ForJob(job)
.Build();
ITrigger trigger1 = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.WithCronSchedule(cron1)
.ForJob(job)
.Build();
// Tell quartz to schedule the job using our trigger
sched.ScheduleJob(trigger);
sched.ScheduleJob(trigger1);
sched.Start();

Jobs not chaining using JobChainingJobListener

I have the current code for my Quartz scheduler:
var scheduler = StdSchedulerFactory.GetDefaultScheduler();
// Job1
var Job1 = JobBuilder.Create<Test1>().WithIdentity("job1", "group1").Build();
// Job2
var Job2 = JobBuilder.Create<Test2>().WithIdentity("job2", "group2").Build();
// Triggers
ITrigger trigger1 = TriggerBuilder.Create().WithIdentity("trigger1", "group1").StartNow().Build()
ITrigger trigger2 = TriggerBuilder.Create().WithIdentity("trigger2", "group2").StartNow().WithSimpleSchedule(x => x.WithIntervalInSeconds(1).WithRepeatCount(4)).Build();
// JobKeys
JobKey jobKey1 = new JobKey("Job1", "group1");
JobKey jobKey2 = new JobKey("Job2", "group2");
// Chain jobs
JobChainingJobListener chain = new JobChainingJobListener("testChain");
chain.AddJobChainLink(jobKey1, jobKey2);
scheduler.ScheduleJob(Job1, trigger1);
scheduler.AddJob(Job2, true);
// Global listener here. I am not sure what I have is correct.
scheduler.ListenerManager.AddJobListener(chain, GroupMatcher<JobKey>.AnyGroup());`
scheduler.Start();
(For clarification, the jobs do nothing more than print to console at the moment.)
From the Quartz website, I found that this will add a JobListener that is interested in all jobs: scheduler.ListenerManager.AddJobListener(chain, GroupMatcher<JobKey>.AnyGroup()); I'm not sure that this is equivalent to a global listener.
I also found that some code where people have done scheduler.addGlobalJobListener(chain); in Java. Is there an equivalent method in c#?
My code compiles and seems to run without errors, but Job2 does not trigger. Job1 prints properly to console.
The issue here is that you have misspelled the key the second time ("Job1" vs "job1") which causes there to be no known link to fire. Here's updated code sample with redundancies removed.
var scheduler = StdSchedulerFactory.GetDefaultScheduler();
JobKey jobKey1 = new JobKey("job1", "group1");
JobKey jobKey2 = new JobKey("job2", "group2");
var job1 = JobBuilder.Create<Test1>().WithIdentity(jobKey1).Build();
var job2 = JobBuilder.Create<Test2>().WithIdentity(jobKey2).StoreDurably(true).Build();
ITrigger trigger1 = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.StartNow()
.Build();
JobChainingJobListener chain = new JobChainingJobListener("testChain");
chain.AddJobChainLink(jobKey1, jobKey2);
scheduler.ListenerManager.AddJobListener(chain, GroupMatcher<JobKey>.AnyGroup());
scheduler.ScheduleJob(job1, trigger1);
scheduler.AddJob(job2, true);
scheduler.Start();
The scheduler.addGlobalJobListener is old API and longer part of 2.x series. You should use the ListenerManager like you have done.

Categories