githubEdit

Quartz

Quartz.NETarrow-up-right is one of the most widely used enterprise-grade scheduling libraries in the .NET community. Brighter provides first-class integration with Quartz for scheduler functionality, making it an excellent choice for production systems requiring durable, distributed scheduling.

Quartz.NET Overview

Quartz.NET is a full-featured, open-source job scheduling system that can be used from smallest apps to large-scale enterprise systems. It provides:

  • Persistent Job Stores: Store jobs and triggers in databases

  • Clustering: Run multiple scheduler instances for HA

  • Trigger Types: Simple, Cron, Calendar-based triggers

  • Job Chains: Execute jobs in sequence

  • Job Data: Pass data to jobs

  • Listeners: Monitor job execution

  • Plugins: Extend functionality

For more information, visit the Quartz.NET documentationarrow-up-right.

How Brighter Integrates with Quartz

Brighter integrates with Quartz through:

  1. QuartzBrighterJob: A Quartz job that executes scheduled Brighter messages

  2. BrighterResolver: Custom job factory that resolves jobs from DI container

  3. QuartzSchedulerFactory: Factory that creates Brighter's message scheduler backed by Quartz

When you schedule a message with Brighter:

  1. Brighter creates a Quartz job with the message payload

  2. Quartz persists the job to its job store

  3. At the scheduled time, Quartz fires the job

  4. QuartzBrighterJob receives the job execution

  5. QuartzBrighterJob dispatches the message via Brighter's Command Processor

  6. Your handler executes

NuGet Packages

Install the required NuGet packages:

For persistence, add a Quartz job store package:

Configuration

Basic Configuration

Configure Brighter with Quartz scheduler:

Configuration with Persistent Job Store

For production, use a persistent job store:

Configuration with appsettings.json

You can configure Quartz via appsettings.json:

Then configure with:

Persistence Options

Quartz supports multiple persistent job stores:

SQL Server

Database Scripts: SQL Server Scriptsarrow-up-right

PostgreSQL

Database Scripts: PostgreSQL Scriptsarrow-up-right

MySQL

Database Scripts: MySQL Scriptsarrow-up-right

In-Memory (Development Only)

For development, you can use the in-memory store (no persistence):

Warning: In-memory store loses all jobs on restart. Use persistent store for production.

Advanced Configuration

Custom Scheduler ID Generation

By default, Brighter uses Guid.NewGuid() for scheduler IDs. Customize this behavior:

Why customize?

  • Use business-meaningful IDs for better tracking

  • Correlate scheduled jobs with business entities

  • Simplify debugging and monitoring

Quartz Job Groups

Organize jobs into groups:

Benefits:

  • Logical organization of jobs

  • Easier monitoring and management

  • Group-level operations (pause, resume, delete)

Misfire Handling

Configure how Quartz handles missed triggers:

Code Examples

Basic Scheduling

Cancelling a Scheduled Job

Scheduling with Absolute Time

Clustering and High Availability

Quartz supports clustering for high availability:

How clustering works:

  1. Multiple scheduler instances share the same job store (database)

  2. Each instance regularly checks in with the job store

  3. If an instance fails, other instances take over its jobs

  4. Only one instance executes each job (no duplicates)

  5. Provides automatic failover and load distribution

Best practices for clustering:

  • Use SchedulerId = "AUTO" for unique instance IDs

  • Set appropriate check-in intervals (default 20 seconds)

  • Use persistent job store (required for clustering)

  • Ensure clocks are synchronized across instances (NTP)

  • Monitor instance health and check-ins

Monitoring and Observability

Quartz Listeners

Monitor job execution with listeners:

Health Checks

Monitor Quartz scheduler health:

Best Practices

1. Always Use Persistent Job Store in Production

2. Enable Clustering for High Availability

3. Store Scheduler IDs for Cancellation

4. Use JSON Serialization

5. Configure Appropriate Check-In Intervals

6. Monitor Job Execution

7. Handle Timezone Correctly

8. Set Appropriate Connection Pool Size

Troubleshooting

Jobs Not Executing

Symptom: Jobs scheduled but never execute

Possible Causes:

  1. Quartz scheduler not started

  2. Database connectivity issues

  3. QuartzBrighterJob not registered

  4. Misfire threshold exceeded

Solutions:

Jobs Executing Multiple Times

Symptom: Same job executes on multiple instances

Cause: Clustering not configured or clock drift

Solution:

Database Deadlocks

Symptom: Database deadlocks in Quartz tables

Cause: High concurrency with insufficient connection pool

Solution:

Migration from Other Schedulers

From InMemory Scheduler

From Hangfire

If migrating from Hangfire, you can run both schedulers during transition:

Summary

Quartz.NET is an excellent production scheduler for Brighter offering:

  • Durability: Jobs persisted to database survive restarts

  • Clustering: High availability with automatic failover

  • Maturity: Battle-tested in production for years

  • Flexibility: Rich API for complex scheduling scenarios

  • Reliability: Strong guarantees for job execution

  • Monitoring: Comprehensive monitoring and observability

  • Strong Naming: Fully signed assemblies for enterprise use

Use Quartz when you need a robust, enterprise-grade scheduler with clustering support and don't require a built-in dashboard (otherwise consider Hangfire).

Last updated

Was this helpful?