# Quartz.NET Usage This sample illustrates the use of [Quartz.NET](https://www.quartz-scheduler.net/) to send messages from within an NServiceBus endpoint. > Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems. ## Running the project 1. Start both the Scheduler and Receiver projects. 1. At startup, Scheduler will schedule a message send to Receiver every 3 seconds. 1. Receiver will handle the message. ## Code Walk-through ### Context Helper A helper to inject and extract the `IMessageSession` from the Quartz scheduler context. ```cs public static class QuartzContextExtensions { public static IMessageSession MessageSession(this IJobExecutionContext context) { return (IMessageSession) context.Scheduler.Context["MessageSession"]; } public static void SetMessageSession(this IScheduler scheduler, IMessageSession messageSession) { scheduler.Context["MessageSession"] = messageSession; } } ``` Quartz also support Dependency Injection (DI) via the [JobFactory API](https://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/miscellaneous-features.html). ### Configure and start the scheduler The endpoint is started, and the `IMessageSession` is injected into the Quartz scheduler context. ```cs var builder = Host.CreateApplicationBuilder(); builder.Services.AddNServiceBusEndpoint(endpointConfiguration); using var host = builder.Build(); var messageSession = host.Services.GetRequiredService(); await host.StartAsync(); LogProvider.SetCurrentLogProvider(new QuartzConsoleLogProvider()); var schedulerFactory = new StdSchedulerFactory(); var scheduler = await schedulerFactory.GetScheduler(); // inject the messageSession into the scheduler context scheduler.SetMessageSession(messageSession); await scheduler.Start(); ``` ### Job definition A Quartz `IJob` that sends a message to Receiver. ```cs public class SendMessageJob : IJob { public async Task Execute(IJobExecutionContext context) { try { var messageSession = context.MessageSession(); var message = new MyMessage(); await messageSession.Send("Samples.QuartzScheduler.Receiver", message); } catch (Exception exception) { Console.WriteLine($"Execution Failed: {exception.Message}"); // TODO: handle exception and dont throw. // consider implementing a circuit breaker throw; } } } ``` Note `QuartzContextExtensions` is used to get access to the `IMessageSession`. ### Schedule a job ```cs // define the job and tie it to the SendMessageJob class var job = JobBuilder.Create() .WithIdentity("job1", "group1") .Build(); // Trigger the job to run now, and then repeat every 3 seconds var trigger = TriggerBuilder.Create() .WithIdentity("trigger1", "group1") .StartNow() .WithSimpleSchedule( action: builder => { builder .WithIntervalInSeconds(3) .RepeatForever(); }) .Build(); // Tell quartz to schedule the job using the trigger await scheduler.ScheduleJob(job, trigger); ``` ### Cleanup The Quartz scheduler should be shut down when the endpoint is stopped. ```cs await scheduler.Shutdown(); await host.StopAsync(); ``` ### Exception Handling Quartz recommendations for [Handling Exceptions](https://www.quartz-scheduler.net/documentation/best-practices.html#handle-exceptions): > Every listener method should contain a try-catch block that handles all possible exceptions. If a listener throws an exception, it may cause other listeners not to be notified and/or prevent the execution of the job, etc. In the catch block of a job, consider either implementing a [circuit breaker](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern) or delegating to [critical errors](/nservicebus/hosting/critical-errors.md). ## Scale Out When using the approach in the sample, it is important to note that there is an instance of the Quartz scheduler running in every endpoint instance. If an endpoint is [scaled out](/nservicebus/scaling.md), then the configured jobs will be executed in each of the running instances. A persistent [Quartz JobStore](https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/job-stores.html) can help manage the the Quartz scheduler shared state including jobs, triggers, calendars, etc. ## Further information on Quartz * [Quartz.NET Quick Start Guide](https://www.quartz-scheduler.net/documentation/quartz-3.x/quick-start.html) * [Quartz.NET Tutorial](https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/index.html)