# Message Scheduler

The scheduling API consists of several extension methods that send messages to an endpoint where the Quartz scheduling consumers are connected.

# Configuring the Quartz address

The bus has an internal context that is used to make it so that consumers that need to schedule messages do not have to be aware of the specific scheduler type being used, or the message scheduler address. To configure the address, use the extension method shown below.

var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
    var host = cfg.Host(new Uri("rabbitmq://localhost/"), h =>
    {
        h.Username("guest");
        h.Password("guest");
    });

    cfg.UseMessageScheduler(new Uri("rabbitmq://localhost/quartz"));
});

Once configured, messages may be scheduled from any message consumer as shown below.

# Scheduling a message from a consumer

To schedule a message, call the ScheduleSend method with the message to be delivered.

public interface ScheduleNotification
{
    DateTime DeliveryTime { get; }
    string EmailAddress { get; }
    string Body { get; }
}

public interface SendNotification
{
    string EmailAddress { get; }
    string Body { get; }
}

public class ScheduleNotificationConsumer :
    IConsumer<ScheduleNotification>
{
    Uri _notificationService;

    public async Task Consume(ConsumeContext<ScheduleNotification> context)
    {
        await context.ScheduleSend(_notificationService,
            context.Message.DeliveryTime,
            new SendNotification
            {
                EmailAddress = context.Message.EmailAddress,
                Body =  context.Message.Body
            });
    }

    class SendNotificationCommand :
        SendNotification
    {
        public string EmailAddress { get; set; }
        public string Body { get; set; }
    }
}

The ScheduleMessage command message will be sent to the Quartz endpoint, which will schedule a job in Quartz to deliver the message (and save the message body to be delivered). When the job is triggered, the message will be sent to the destination address.

# Scheduling a message from the bus

If a message needs to be scheduled from the bus itself (not in the context of consuming a message), the SendEndpoint for the Quartz scheduler should be retrieved and used to schedule the send.

var schedulerEndpoint = await bus.GetSendEndpoint(_schedulerAddress);    
                                                                    
await schedulerEndpoint.ScheduleSend(_notificationService,                   
    context.Message.DeliveryTime,                                            
    new SendNotification                                                     
    {                                                                        
        EmailAddress = context.Message.EmailAddress,                         
        Body =  context.Message.Body                                         
    });

This should only be used outside of a consume context, however, as the lineage of the message will be lost (things like ConversationId, InitiatorId, etc.).

# Recurring Messages

You can also schedule a message to be send to you periodically. This functionality uses the Quartz.Net periodic schedule feature and requires some knowledge of cron expressions.

To request a recurring message, you need to use ScheduleRecurringSend extension method, which is available for both Context and SendEndpoint. This message requires a schedule object as a parameter, which must implement RecurringSchedule interface. Since this interface is rather broad, you can use the default abstract implementation DefaultRecurringSchedule as the base class for your own schedule.

public class PollExternalSystemSchedule : DefaultRecurringSchedule
{
    public PollExternalSystemSchedule()
    {
        CronExpression = "0 0/1 * 1/1 * ? *"; // this means every minute
    }
}

public class PollExternalSystem {}
var schedulerEndpoint = await bus.GetSendEndpoint(_schedulerAddress);
    
var scheduledRecurringMessage = await schedulerEndpoint.ScheduleRecurringSend(
    InputQueueAddress, new PollExternalSystemSchedule(), new PollExternalSystem());

When you stop your service or just have any other need to tell Quartz service to stop sending you these recurring messages, you can use the return value of ScheduleRecurringSend to cancel the recurring schedule.

await bus.CancelScheduledRecurringMessage(scheduledRecurringMessage);

You can also cancel using schedule id and schedule group values, which are part of the recurring schedule object.