Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

FluentScheduler Usage

Component: NServiceBus
NuGet Package: NServiceBus (9.x)

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);

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();

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 designing a solution that requires scale out. For example, message de-duplication may be required, or the scheduler might need to be run 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
    Message store for delayed messages sent with NServiceBus.