# Scheduling

Time is important, particularly in distributed applications. Sophisticated systems need to schedule things, and MassTransit has extensive scheduling support.

MassTransit supports two different methods of message scheduling:

  1. Scheduler-based, using either Quartz.NET or Hangfire, where the scheduler runs in a service and schedules messages using a queue.
  2. Transport-based, using the transports built-in message scheduling/delay capabilities. In some cases, such as RabbitMQ, this requires an additional plug-in to be installed and configured.

Recurring schedules are only supported by scheduler-based solutions (Option 1).

# Configuration

Depending upon the scheduling method used, the bus must be configured to use the appropriate scheduler.

# Quartz.NET / Hangfire

To configure the bus to use either Quartz.NET or Hangfire for message scheduling, add the UseMessageScheduler method as shown below.

namespace SchedulingEndpoint
{
    using System;
    using MassTransit;
    using Microsoft.Extensions.DependencyInjection;

    public class Program
    {
        public static void Main()
        {
            var services = new ServiceCollection();

            Uri schedulerEndpoint = new Uri("queue:scheduler");

            services.AddMassTransit(x =>
            {
                x.AddMessageScheduler(schedulerEndpoint);

                x.UsingRabbitMq((context, cfg) => 
                {
                    cfg.UseMessageScheduler(schedulerEndpoint);

                    cfg.ConfigureEndpoints(context);
                });
            });
        }
    }
}

The UseMessageScheduler configures the bus to use the scheduler endpoint. The AddMessageScheduler adds IMessageScheduler to the container, which will use the same scheduler endpoint.

Quartz.NET Docker Image

MassTransit provides a Docker Image with Quartz.NET ready-to-run using SQL Server. A complementary SQL Server Image configured to run with Quartz.NET is also available. Combined, these images make getting started with Quartz easy.

Quartz.NET can also be configured in-memory, which is great for unit testing.

Uses MassTransit.Quartz

namespace SchedulingInMemory
{
    using System;
    using MassTransit;
    using Microsoft.Extensions.DependencyInjection;

    public class Program
    {
        public static void Main()
        {
            var services = new ServiceCollection();

            services.AddMassTransit(x =>
            {
                x.AddMessageScheduler(new Uri("queue:scheduler"));

                x.UsingRabbitMq((context, cfg) => 
                {
                    cfg.UseInMemoryScheduler("scheduler");

                    cfg.ConfigureEndpoints(context);
                });
            });
        }
    }
}

The UseInMemoryScheduler method initializes Quartz.NET for standalone in-memory operation, and configures a receive endpoint named scheduler. The AddMessageScheduler adds IMessageScheduler to the container, which will use the same scheduler endpoint.

WARNING

Using the in-memory scheduler uses non-durable storage. If the process terminates, any scheduled messages will be lost, immediately, never to be found again. For any production system, using a standalone service is recommended with persistent storage.

# Transport-based

To configure transport-based message scheduling, refer to the transport-specific section for details.