In my journal to cover all Brighter feature, I've already talked about Hangfire. Now I want to talk about Quartz.NET scheduler with Brighter.
What and Why Quartz.NET?
Quartz.NET is a powerful, full-featured open source job scheduling system that offers:
- Persistent job storage: Jobs survive application restarts
- Clustering support: Distribute scheduled jobs across multiple nodes
- Recoverability: Automatic recovery of failed jobs
- Sophisticated triggers: Time-based, calendar-based, and composite triggers
While Brighter provides built-in scheduling capabilities, Quartz.NET offers more sophisticated scheduling options that are essential for enterprise applications requiring precise timing control and job persistence.
Requirement
- .NET 8 or superior (Brighter V10 supports net8.0, net9.0 and netstandard2.0)
- A .NET project with these NuGet packages
- Quartz.Extensions.Hosting: Enables Quart.NET integration with ASP.NET Core.
- Paramore.Brighter.MessageScheduler.Quartz: Integrates Quart.Net with Brighter's scheduling system.
- Paramore.Brighter.MessagingGateway.Postgres: Enables Postgres integration for message queuing.
- Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection: Enable register Brighter with Microsoft DI.
- Paramore.Brighter.ServiceActivator.Extensions.Hosting: Hosts Brighter as a background service.
- Serilog.AspNetCore: For structured logging (optional but recommended).
Brighter Recap
Before diving into the Quartz.NET integration, let's briefly review key Brighter concepts:
Request (Command/Event)
Define messages using IRequest
:
public class Greeting() : Event(Id.Random())
{
public string Name { get; set; } = string.Empty;
}
- Commands: Single-recipient operations (e.g.,
SendEmail
). - Events: Broadcast notifications (e.g.,
OrderShipped
).
Message Mapper (Optional)
Translates between Brighter messages and your app objects, by default Brighter will use JSON serialize.
Request Handler
Processes incoming messages:
public class GreetingHandler(ILogger<GreetingHandler> logger) : RequestHandler<Greeting>
{
public override Greeting Handle(Greeting command)
{
logger.LogInformation("Hello {Name}", command.Name);
return base.Handle(command);
}
}
Configuring Brighter with Quartz.NET Scheduler
1. Register Quartz.NET into Microsoft DI
For development, you can use in-memory storage, but for production environments, always use a persistent storage solution like PostgreSQL
, SQL Server
:
services
.AddQuartz(opt =>
{
opt.SchedulerId = "QuartzBrighter";
opt.SchedulerName = "QuartzBrighter";
opt.UseSimpleTypeLoader();
opt.UseInMemoryStore();
})
.AddQuartzHostedService(opt =>
{
opt.WaitForJobsToComplete = true;
});
2. Register Quartz.NET on Brighter
For registering the Quartz scheduler in Brighter, we can use the ISchedulerFactory
provided by Quart.NET by:
services
.AddHostedService<ServiceActivatorHostedService>()
.AddServiceActivator(opt => ... )
.UseScheduler(provider =>
{
var factory = provider.GetRequiredService<ISchedulerFactory>();
return new QuartzSchedulerFactory(factory.GetScheduler().GetAwaiter().GetResult());
})
3. Using the Scheduler
Schedule messages with precise timing control using either relative (TimeSpan
) or absolute (DateTimeOffset
) timing:
// Schedule for 1 second from now
await process.PostAsync(TimeSpan.FromSeconds(1), new SchedulerCommand { Name = name, Type = "Post"});
// Schedule for 2 seconds from now
await process.SendAsync(TimeSpan.FromSeconds(2), new SchedulerCommand { Name = name, Type = "Send"});
// Schedule for exactly 3 seconds from now
await process.PublishAsync(DateTimeOffset.UtcNow + TimeSpan.FromSeconds(3), new SchedulerCommand { Name = name, Type = "Publish"});
Conclusion
Integrating Quartz.NET with Brighter provides a robust scheduling solution for enterprise applications requiring precise timing control and job persistence. While Brighter offers basic scheduling capabilities, Quartz.NET adds enterprise-grade features that are essential for production environments.
By following this guide, you can implement a reliable message scheduling system that combines Brighter's messaging capabilities with Quartz.NET's sophisticated scheduling features, creating a powerful foundation for your distributed applications.
Remember to always use persistent storage for Quartz in production environments, and consider implementing proper monitoring for your scheduled jobs to ensure timely delivery of your messages.
Top comments (0)