QuartzNet - austincodecamp09

advertisement

Asynchronous Job Processing

Using Quartz.Net

Jay Vilalta jay.vilalta@gmail.com

What Is Quartz.Net

• Scheduler (think task scheduler)

• Queue for asynchronous jobs

• C# port of Quartz (java)

• Apache license

Why Use Quartz.Net

• Scale out

• Redundancy

• Smart handling of failures

• Job chaining (poor man’s workflow)

• Custom scheduling

How Can I Run It

• Embedded in your application

• As a stand alone windows service

• Scheduler

• Jobs

• Triggers

The Basics

Scheduler

• Runs jobs

• Manages the scheduling

• Do the work

• Some built-in

• Mostly roll you own

• Implement IJob

Jobs

Built-in Jobs

• FileScanJob: monitors last modified date

• NativeJob: runs executables or batch files

• NoOpJob: does nothing

• SendMailJob: sends emails

Jobs - Example

} public class MyJob : IJob { public void Execute(JobExecutionContext context) { try { int count= context.MergedJobDataMap.GetIntegerFromString(“count"); for (int i = 0; i < count; i++) {

//do something useful

}

}

} catch (ApplicationException ex) { throw new JobExecutionException("Something happened", ex, false);

}

Triggers

• Tell the scheduler when jobs should run

• Some built-in

– Simple Trigger

– Cron Trigger

– NthIncludedDayTrigger

• Custom Triggers

Simple Trigger

• Start Time

• Repeat Count

• Repeat Interval

Cron Trigger

• Similar to UNIX cron

• Start Time

• Cron Expression

– “0 15 10 ? * *”

– “0 0,15,30,45 * ? * *”

Custom Triggers

• No example this time

• Implementing a trigger is not trivial

• Must implement 11 methods

• Must be able to determine next fire time

Scheduling

• Associate a job to a trigger

• Multiple triggers can be set

• When the trigger fires, the job runs scheduler.ScheduleJob(jobDetail, trigger);

Advanced Features

• Listeners

• Special Jobs

• Remote management

• Clustering

• Plug-ins

• Unit testing

Listeners

• Job Listeners

• Trigger Listeners

• Scheduler Listeners

• Job and trigger listeners can be global

Job Listener Example

}

{ public class JobHistoryListener : IJobListener public void JobExecutionVetoed(…) public void JobToBeExecuted(…) public void JobWasExecuted(…)

Trigger Listener Example

}

{ public class MyTriggerListener:ITriggerListener public string Name public void TriggerComplete(…) public void TriggerFired(…) public void TriggerMisfired(…) public bool VetoJobExecution(…)

Special Jobs

• Stateful Jobs

• Interruptible Jobs

Stateful Jobs

• Only one can run at a time

• Allow you to save/restore state

• You must manage state yourself

• Implement IStatefulJob

Interruptible Jobs

• Mechanism to interrupt long running jobs

• You must implement yourself

• Implement IInterruptableJob

Remote Management

• Scheduler can be managed remotely

• Exposed via Remoting

• Most scheduler functions available

JobFactory

• Instantiates jobs

• Default factory creates a new instance

• Create your own if you use DI or IoC container

• RAMJobStore

• AdoJobStore

– MySql

– Oracle

– Postgres

– SQL Lite

– SQL Server

Job Stores

Clustering

• Load balancing

• Job Failover

• Caveat: clocks synchronized within a second

Plug-ins

• JobInitializationPlugin

• LoggingJobHistoryPlugin

• LoggingTriggerHistoryPlugin

• ShutdownHookPlugin

Plug-ins Stub public class SamplePlugin : ISchedulerPlugin

{ public void Initialize(string name, IScheduler sched) public void Shutdown() public void Start()

}

Unit Testing

• You can / should unit test your quartz classes

• Use a mocking framework

• Mock the Scheduler (IScheduler)

• Mock a calendar (ICalendar)

• Use mocks to create your context

Sample Unit Test

[Test] public void ExecuteTests()

{

JobDetail detail = new JobDetail();

IScheduler scheduler = new Mock<IScheduler>().Object;

ICalendar calendar = new Mock<ICalendar>().Object;

IJob job = new NoOpJob(); detail.Name = "Test"; detail.JobDataMap.Add("SOMETHING", "ELSE");

TriggerFiredBundle bundle = new TriggerFiredBundle(detail, new SimpleTrigger(), calendar, false, null, null, null, null);

JobExecutionContext context = new JobExecutionContext(scheduler, bundle, job);

JobHistoryListener listener = new JobHistoryListener(); listener.JobToBeExecuted(context); listener.JobWasExecuted(context, null);

//methods return void so need to get creative to determine if execution was successful

}

}

Resources

Project Home: http://quartznet.sourceforge.net/

Mailing List: http://groups.google.com/group/quartznet

Getting Started: http://jvilalta.blogspot.com

Download