FluentScheduler Usage

Component: NServiceBus
NuGet Package NServiceBus (7-pre)
This page targets a pre-release version and is subject to change prior to the final release.

This sample illustrates the use of FluentScheduler to send messages from within an NServiceBus endpoint.

The approach used in this sample can mitigate some of the architectural drawbacks of the NServiceBus Scheduler. The NServiceBus scheduler is built on top of the Timeout Manager which leverages the queuing system to trigger scheduled actions. Under heavy load there may be some disparity between the expected time of a scheduled action and execution time due to the delay between timeout messages being generated and processed.

Running the project

  1. Start both the Scheduler and Receiver projects.
  2. At startup Scheduler will schedule sending a message to Receiver every 3 seconds.
  3. Receiver will handle the message.

Code Walk-through

Configure and start the scheduler

The endpoint is started and the IEndpointInstance is stored in the static endpoint helper.

var endpointInstance = await Endpoint.Start(endpointConfiguration)
    .ConfigureAwait(false);

JobManager.AddJob(
    new SendMessageJob(endpointInstance),
    schedule =>
    {
        schedule
            .ToRunNow()
            .AndEvery(3).Seconds();
    });

Job definition

public class SendMessageJob : IJob
{
    IEndpointInstance endpoint;

    public SendMessageJob(IEndpointInstance endpoint)
    {
        this.endpoint = endpoint;
    }

    public void Execute()
    {
        endpoint.Send("Samples.FluentScheduler.Receiver", new MyMessage())
            .GetAwaiter().GetResult();
    }
}

FluentScheduler does not currently have native support for async. As such the job execution is blocked with .GetAwaiter().GetResult().

Dependency Injection is supported for more advanced scenarios. For example injecting IEndpointInstance into the IJob constructor.

Cleanup

The JobManager should be cleaned up when the endpoint is shut down.

JobManager.StopAndBlock();
await endpointInstance.Stop()
    .ConfigureAwait(false);

Logging

FluentScheduler exposes events that can be helpful to log.

var logger = LogManager.GetLogger(typeof(JobManager).FullName);
JobManager.JobException += info =>
{
    logger.Error($"Error occurred in job: {info.Name}", info.Exception);
};
JobManager.JobStart += info =>
{
    logger.Info($"Start job: {info.Name}. Duration: {info.StartTime}");
};
JobManager.JobEnd += info =>
{
    logger.Info($"End job: {info.Name}. Duration: {info.Duration}. NextRun: {info.NextRun}.");
};

Scale Out

Note that in this sample an instance of the FluentScheduler is configured to run in every endpoint's instance. If an endpoint is scaled out then the configured jobs will be executed by each of the running instances. This behavior needs to be considered when architecting a solution that requires scale out. For example message de-duplication may be required, or only running the scheduler on a single endpoint instance.

Further information on FluentScheduler

Related Articles

  • Scheduling
    Schedule a task or an action/lambda, to be executed repeatedly at a given interval.
  • Timeout Manager
    NServiceBus persistent delayed message store.

Last modified