Configuring Jobs Using Quartz.Net and The CloudConfigurationManager

April 3, 2013 — 1 Comment

homer_simpson_clockA few weeks ago I wrote about using Quartz.Net to schedule jobs in Windows Azure Worker Roles. Since then I ran into a requirement that pushed me to create a wrapper around the Quartz.Net IScheduler. The JobSchedule has the responsibility of reading a schedule string from the CloudConfigurationManager and schedule a job.

The CloudConfigurationManager reads settings from the Role’s configuration file, which can be edited through the Windows Azure Management Portal under the configure section of your cloud services.

The following example will schedule a job which needs to be executed everyday at 6 AM, 8 AM, 10 AM, 12:30 PM and at 4:30 PM. The schedule is defined in the Role settings which can be edited through Visual Studio. To reach the Role settings, go to your Windows Azure Cloud Service project and find the desired Role configurations under the Role folder. Open the configuration editor by double clicking on the configuration file, then navigate to the ‘Settings’ tab. Click on ‘Add Setting’ and name the new setting ‘JobDailySchedule’ and set its value to 6:0;8:0;10:0;12:30;16:30;

The code from this Post is part of the Brisebois.WindowsAzure NuGet Package

To install Brisebois.WindowsAzure, run the following command in the Package Manager Console

PM> Install-Package Brisebois.WindowsAzure

Get more details about the Nuget Package.

Then using the JobSchedule schedule a daily job using the schedule defined in the Role’s configuration file.

var schedule = new JobSchedule();

schedule.ScheduleDailyJob("JobDailySchedule",
                            typeof(DailyJob));

The DailyJob implementation goes as follows. Since this is a demo, I will not add any specific logic to the job.

public class DailyJob : IJob
{
    public void Execute(IJobExecutionContext context)
    {
        //Do your daily work here
    }
}

The JobSchedule wraps the Quartz.Net IScheduler. In a previous post I spoke about the importance of wrapping your 3rd party tools, this is an excellent example because I am containing the job scheduling logic and I could potentially change this logic without affecting the code that is using the JobSchedule.

The JobSchedule should be configured when the Role starts and the JobSchedule instance should be maintained throughout the Role’s lifetime. Changing the schedule can be achieved by changing the  ‘JobDailySchedule’ setting through the Windows Azure Management Portal under the configure section of your cloud services. Then to apply the new schedule, restart the Role instance through the Windows Azure Management Portal under the instances section of your cloud services.

public class JobSchedule
{
    private readonly IScheduler sched;

    public JobSchedule()
    {
        var schedFact = new StdSchedulerFactory();

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

    /// <summary>
    /// Will schedule jobs in Eastern Standard Time
    /// </summary>
    /// <param name="scheduleConfig">Setting Key from your CloudConfigurations, 
    ///                              value format "hh:mm;hh:mm;"</param>
    /// <param name="jobType">must inherit from IJob</param>
    public void ScheduleDailyJob(string scheduleConfig, 
                                 Type jobType)
    {
        ScheduleDailyJob(scheduleConfig, 
                         jobType, 
                         "Eastern Standard Time");
    }

    /// <param name="scheduleConfig">Setting Key from your CloudConfigurations, 
    ///                              value format "hh:mm;hh:mm;"</param>
    /// <param name="jobType">must inherit from IJob</param>
    public void ScheduleDailyJob(string scheduleConfig, 
                                 Type jobType, 
                                 string timeZoneId)
    {
        var schedule = CloudConfigurationManager.GetSetting(scheduleConfig);
        if (schedule == "-")
            return;

        schedule.Split(';')
                .Where(s => !string.IsNullOrWhiteSpace(s))
                .ToList()
                .ForEach(h =>
        {
            var index = h.IndexOf(':');
            var hour = h.Substring(0, index);
            var minutes = h.Substring(index + 1, h.Length - (index + 1));

            var job = new JobDetailImpl(jobType.Name + hour + minutes, null,
                                        jobType);

            var dh = Convert.ToInt32(hour, CultureInfo.InvariantCulture);
            var dhm = Convert.ToInt32(minutes, CultureInfo.InvariantCulture);
            var tz = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);

            var cronScheduleBuilder = CronScheduleBuilder
                                            .DailyAtHourAndMinute(dh, dhm)
                                            .InTimeZone(tz);
            var trigger = TriggerBuilder.Create()
                                        .StartNow()
                                        .WithSchedule(cronScheduleBuilder)
                                        .Build();

            sched.ScheduleJob(job, trigger);
        });
    }

    /// <summary>
    /// Will schedule jobs in Eastern Standard Time
    /// </summary>
    /// <param name="scheduleConfig">Setting Key from your CloudConfigurations, 
    ///                              value format "hh:mm;hh:mm;"</param>
    /// <param name="jobType">must inherit from IJob</param>
    public void ScheduleWeeklyJob(string scheduleConfig, 
                                  Type jobType)
    {
        ScheduleWeeklyJob(scheduleConfig, 
                          jobType, 
                          "Eastern Standard Time");
    }


    /// <param name="scheduleConfig">Setting Key from your CloudConfigurations,
    ///                              value format "hh:mm;hh:mm;"</param>
    /// <param name="jobType">must inherit from IJob</param>
    public void ScheduleWeeklyJob(string scheduleConfig, 
                                  Type jobType, 
                                  string timeZoneId)
    {
        var schedule = CloudConfigurationManager.GetSetting(scheduleConfig);

        schedule.Split(';')
                .Where(s => !string.IsNullOrWhiteSpace(s))
                .ToList()
                .ForEach(h =>
        {
            var index = h.IndexOf(':');
            var hour = h.Substring(0, index);
            var minutes = h.Substring(index + 1, h.Length - (index + 1));

            var job = new JobDetailImpl(jobType.Name + hour + minutes, null,
                                        jobType);

            var dh = Convert.ToInt32(hour, CultureInfo.InvariantCulture);
            var dhm = Convert.ToInt32(minutes, CultureInfo.InvariantCulture);
            var tz = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
            var builder = CronScheduleBuilder
                            .WeeklyOnDayAndHourAndMinute(DayOfWeek.Monday, 
                                                         dh, 
                                                         dhm)
                            .InTimeZone(tz);

            var trigger = TriggerBuilder.Create()
                                        .StartNow()
                                        .WithSchedule(builder)
                                        .Build();

            sched.ScheduleJob(job, trigger);
        });
    }
}

Trackbacks and Pingbacks:

  1. Dew Drop – April 4, 2013 (#1,520) | Alvin Ashcraft's Morning Dew - April 4, 2013

    […] Configuring Jobs Using Quartz.Net and The CloudConfigurationManager (Alexandre Brisebois) […]

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.