Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reschedule Quartz job scheduler in C# dynamically from database?

I have included Quartz.net library in my C#.Net website to send emails automatically based on some conditions. I have started the job to with RepeatForever(). I am getting the settings for the scheduler from database. Now when the job has already started is there anyway to check if the settings for the scheduler in the database have changed so i should also update them in my method so that scheduler runs with the new settings dynamically? So far I have done this:

public void StartJob()
    {
        var reminderSettings = GetReminderSettings();  //getting these settings from database
        var count = GetUnpaidInvoicesListCount();
        var intervalBtwnReminders = 0;
        if (reminderSettings?.RemindersGap != null)
        {
            intervalBtwnReminders = (int)(reminderSettings.RemindersGap);         
        }

        ISchedulerFactory schedFact = new StdSchedulerFactory();

        IScheduler sched = schedFact.GetScheduler();
        sched.Start();

        // create job
        IJobDetail job = JobBuilder.Create<EmailJob>()
                .WithIdentity("job1", "group1")
                .Build();

        // create trigger
        ITrigger trigger = TriggerBuilder.Create()
            .WithIdentity("trigger1", "group1")
            .WithSimpleSchedule(x =>
            {
                 x.WithIntervalInMinutes(intervalBtwnReminders ).RepeatForever();
            })
            .Build();

        sched.ScheduleJob(job, trigger);
    }
like image 709
Harry .Naeem Avatar asked Jan 11 '17 11:01

Harry .Naeem


1 Answers

I wrote a set of methods to make it more easy. You can't edit an existing trigger with your new interval, but you can replace your existing trigger with a new one. The CreateTrigger method creates a new Trigger based on a old one and transfers the TimesTriggered count.

/// <summary>
/// Create a new trigger based on a existing trigger.
/// </summary>
/// <param name="oldTrigger">the existing trigger</param>
/// <param name="startNow">indicates if the trigger should start immediately after schedule</param>
/// <param name="interval">the interval for the new trigger</param>
/// <returns>Returns the new trigger</returns>
public ITrigger CreateTrigger(ITrigger oldTrigger, bool startNow = false, TimeSpan? interval = null)
{
    var builder = oldTrigger.GetTriggerBuilder();
    if (startNow)
        builder = builder.StartNow();
    if (interval.HasValue)
        builder = builder.WithSimpleSchedule(s => s
            .WithInterval(interval.Value)
            .RepeatForever());

    var newTrigger = builder.Build();
    var simpleTrigger = newTrigger as ISimpleTrigger;
    if(simpleTrigger != null)
    {
        var trigger = oldTrigger as ISimpleTrigger;
        if (trigger != null)
            simpleTrigger.TimesTriggered = trigger.TimesTriggered;
    }

    return newTrigger;
}

How to use it

In this example, the Scheduler is already running.

// get the trigger
var trigger = Scheduler.GetTrigger(new TriggerKey("trigger1", "group1"));

// get your settings and set the interval
var reminderSettings = GetReminderSettings();
var intervalBtwnReminders = 0;
if (reminderSettings?.RemindersGap != null)
{
    intervalBtwnReminders = (int)(reminderSettings.RemindersGap);         
}

// reschedule the job with a new trigger and start it immediately.
// if you don't want that it starts now, pass 'false' for the 'startNow' parameter
Scheduler.RescheduleJob(trigger.Key, CreateTrigger(trigger, true, TimeSpan.FromMinutes(intervalBtwnReminders)));
like image 170
Rabban Avatar answered Sep 22 '22 18:09

Rabban