Thursday, April 16, 2009

Getting Started With Quartz.Net Part 5 – Configuring Triggers

NOTE: I'm now blogging at http://jayvilalta.com/blog and not updating this blog anymore. For information on the latest version of Quartz.Net, visit me there.

In Part 4, we explained how to configure jobs in detail. In this final installment of the series we’ll describe how to configure two kinds of triggers: the CronTrigger and the SimpleTrigger.
In keeping with the previous posts, we will configure the triggers in the quartz_jobs.xml file. Part 4 included a sample configuration of a CronTrigger, so let’s start with this. Here is the xml fragment that we are going to work with:
<trigger>
    <cron>
      <name>PayrollProcessorTrigger</name>
      <group>Payroll</group>
      <description>Trigger payroll</description>
      <misfire-instruction>SmartPolicy</misfire-instruction>
      <volatile>false</volatile>
      <job-name>PayrollProcessor</job-name>
      <job-group>Payroll</job-group>
      <cron-expression>0 * * * * ?</cron-expression>
    </cron>
  </trigger>

Common Properties
The first 3 elements should be familiar to you. They are used to describe and identify the trigger. The trigger is identified by both the name and the group.  You can have triggers with the same name as long as they are not in the same group.
The next element on the list is the misfire-instruction. This element tells the scheduler what it should do if the trigger misfires. A trigger misfires when the scheduler is unable to fire the trigger when it was supposed to be fired. This could be because the scheduler was down or too busy, for example. The two built-in types of misfire instructions are InstructionNotSet, which is the default setting if no misfire instruction is specified and SmartPolicy.  The SmartPolicy instruction is a high level instruction that basically asks each trigger to decide what the “smart” thing to do is.
The Cron trigger provides (in addition to the instructions listed above)  the following MisfireInstruction values: FireOnceNow and DoNothing. For a Cron trigger the SmartPolicy instruction translates to FireOnceNow. The names are pretty descriptive as far as what the scheduler should do.
The SimpleTrigger also provides some additional MisfireInstructions: FireNow, RescheduleNowWithExistingRepeatCount, RescheduleNowWithRemainingRepeatCount,RescheduleNextWithRemainingCount and RescheduleNextWithExistingCount. If you select a SmartPolicy MisfireInstruction for the SimpleTrigger, things aren’t that simple anymore. The documentation explains what will happen as follows:
If the Repeat Count is 0, then the instruction will be interpreted as FireNow. If the Repeat Count is RepeatIndefinitely, then the instruction will be interpreted as RescheduleNowWithRemainingRepeatCount. There is also the following warning: using RescheduleNowWithRemainingRepeatCount with a trigger that has a non-null end-time may cause the trigger to never fire again if the end-time arrived during the misfire time span. Finally, if the Repeat Count is > 0, then the instruction will be interpreted as RescheduleNowWithExistingRepeatCount.
As you can see, it’s really not that simple… However, that covers the MisfireInstruction part. Now it’s time to look at the Volatile property, which so happens to be the same as for the Job and that we discussed in Part 4:
The description of the volatile parameter has a double negative in the documentation description, so I’ll try to rephrase it in a way that is a bit less confusing. If you set the volatile parameter to true, the job will not be persisted in the job store when the scheduler is shut down. If you set the volatile parameter to false, the job will get persisted in the job store. Note, however, that if you are using the AdoJobStore, the job will get persisted regardless of the value of this parameter. Also consider the fact that if you are using the in memory data store… no data will get persisted and you will have to re-schedule all the jobs upon start up.
Next up are the JobName and JobGroup properties, which effectively link the trigger to the job. A trigger can only be assigned to one job and the job’s name and group are needed in order to uniquely identify the job. Make sure these match the name and group of the job you want to schedule.
You can also set the trigger’s start and end times, by adding these elements:
<start-time></start-time>
<end-time></end-time>

Make sure you specify the times in UTC!
Cron Trigger Properties
The last property that we need to provide for a Cron trigger is the Cron expression. This expression follows “mostly” the standard cron syntax, but there are some differences that can cause some frustration, so be sure to look at the documentation. The Quartz.Net cron expression documentation is here and the link also has some examples of the most common expressions.
Simple Trigger Properties
Here is an xml fragment for configuring the simple trigger. We’ll only discuss the last two elements, because the rest of them work just as we described above.
<trigger>
  <simple>
    <name>sampleSimpleTrigger</name>
    <group>sampleSimpleGroup</group>
    <description>Simple trigger to simply fire sample job</description>
    <misfire-instruction>SmartPolicy</misfire-instruction>
    <volatile>false</volatile>
    <job-name>sampleJob</job-name>
    <job-group>sampleGroup</job-group>
    <repeat-count>RepeatIndefinitely</repeat-count>
    <repeat-interval>3000</repeat-interval>
  </simple>
</trigger>

The RepeatCount is used to tell the trigger how many times to fire. You can either specify a number or you can specify RepeatIndefinitely, which basically means the trigger keeps firing over and over again.
The RepeatInterval property sets the time interval at which to repeat the trigger. The example is set in milliseconds.
With this last post I think we have covered pretty much everything that you need to know to set up, configure and run a Quartz.Net server.
Thanks for reading!

2 comments:

Anonymous said...

Awesome, Thanks!

Anonymous said...

Really good tutorial!! thanks, I've setup and run everything in less than 10 minutes...

Great Job Man!