Quartz.NET - Learning the new API

I am starting to look at Quartz .NET as potential task scheduler. I used the older version of Quartz.NET in the past and need to see review the new API. The latest version has a new fluent api. The first thing I check is, “Does Quartz .NET have a Nuget Package?”

Checklist

  1. Nuget package? Check
  2. Does Quartz .NET have a website with documentation? Check
  3. Is there a tutorial? Check
  4. Is the tutorial up to date? NO… see comments below.
  5. Is there a Github repo? Check

Quartz Terms

  • Job - The task or job you want to run.
  • Trigger - Trigger objects ‘trigger’ the execution of jobs.
  • Groups - Jobs and Triggers can be grouped together.

Out of Date Documentation

The tutorial is for the older version of Quartz .NET and is no longer applicable. Looking at the Migration Guide gives an example that doesn’t compile.

After some finagling with the code I came up with a simple working example:

// Simple working example
class Program
{
    static void Main(string[] args)
    {
        // construct a scheduler factory
        ISchedulerFactory schedFact = new StdSchedulerFactory();

        // get a scheduler
        IScheduler sched = schedFact.GetScheduler();
        sched.Start();

        IJobDetail jobDetail = JobBuilder.Create<SimpleJob>()
                                            .WithIdentity("job1", "group1")
                                            .Build();

        ITrigger trigger = TriggerBuilder
                       .Create()
                       .WithIdentity("trigger1", "group1")
                       .StartAt(DateBuilder.FutureDate(5, IntervalUnit.Second))
                       .WithSimpleSchedule(x => x.WithInterval(new TimeSpan(0, 0, 0,seconds: 5))
                                                                .RepeatForever())
                        .Build();

        sched.ScheduleJob(jobDetail, trigger);
    }
}

public class SimpleJob : IJob
{
    public SimpleJob(){}

    public void Execute(IJobExecutionContext context)
    {
        Console.WriteLine("SimpleJob is executing.");
    }
}

General Questions

  1. Does Quartz spawn new processes or use the thread pool? Uses the thread pool.
  2. How are the tasks executed? The tasks are executed asynchronously.
  3. How do you configure a job to run on a schedule, say every night at midnight?
        ITrigger trigger = TriggerBuilder
                      .Create()
                      .WithDailyTimeIntervalSchedule(x => x.StartingDailyAt(new TimeOfDay(23, 59)))
                      .Build();
    
  4. How do I stop a Job that is currently executing? See the Quartz.IInterruptableJob interface, and the Scheduler.Interrupt(string, string) method.
  5. How do I persist a job? Create the SQL Tables.
  6. How do I configure the scheduler using a config file? There is an example xml file in GitHub.

Pulling Down the Source

  1. Pulling down the source, since Quartz .NET, is in Github is fairly trivial.
    git clone https://github.com/quartznet/quartznet.git
  2. Next I had to copy nuget.exe to {clone directory}\quartznet.nuget.
  3. Finally I had to “Allow NuGet to download missing packages during the build” by going to Tools > Options in Visual Studio. 

Handy Code Snippets

  1. How you shutdown the scheduler
     sched.Shutdown( waitForJobsToComplete:true );
    
  2. Display some stats about the schedule that just ran
    SchedulerMetaData metaData = sched.GetMetaData();
    log.Info(string.Format("Executed {0} jobs.", metaData.NumberOfJobsExecuted));
    
  3. When a job throws an exception you can handle the exception and rethrow a JobExecutionException.
    try
    {
            int calculation = 4815 / denominator;
    }
    catch (Exception e)
    {
         log.Info("--- Error in job!");
        JobExecutionException e2 = new JobExecutionException(e);
    
         // fix denominator so the next time this job run
         // it won't fail again
          dataMap.Put("denominator", "1");
    
         // this job will refire immediately
    e2.RefireImmediately = true; // or e2.UnscheduleAllTriggers = true;
        throw e2;
    
    }

Reference Links