Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Add feature toggles to handlers

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

This sample leverages the pipeline to optionally skip executing specific handlers. It injects a behavior into the pipeline before a handler is executed and checks a list of feature toggle functions to determine whether or not the handler should be executed. If the handler is skipped, a message is logged.

The handlers

There are two handlers in the sample. Only Handler2 will be executed because Handler1 does not meet the conditions of the feature toggle.

The behavior

The feature toggle behavior contains a list of functions that decide whether the handler should be executed or not. Each toggle function accepts a handler context that contains details about the message being handled and the handler about to be executed. If all of the toggle functions return true, the handler is executed. If any of the toggle functions return false, then the handler is skipped and a message is logged.

class FeatureToggleBehavior :
    Behavior<IInvokeHandlerContext>
{
    static ILog log = LogManager.GetLogger<FeatureToggleBehavior>();

    IList<Func<IInvokeHandlerContext, bool>> toggles;

    public FeatureToggleBehavior(IList<Func<IInvokeHandlerContext, bool>> toggles)
    {
        this.toggles = toggles;
    }

    public override async Task Invoke(IInvokeHandlerContext context, Func<Task> next)
    {
        if (toggles.All(toggle => toggle(context)))
        {
            await next();
        }
        else
        {
            log.InfoFormat("Feature toggle skipped execution of handler: {0}", context.MessageHandler.HandlerType, context.MessageHandler);
        }
    }
}

The feature

The feature toggle's feature creates the behavior and adds it to the pipeline.

class FeatureToggles : Feature
{
    protected override void Setup(FeatureConfigurationContext context)
    {
        var settings = context.Settings.Get<FeatureToggleSettings>();
        var behavior = new FeatureToggleBehavior(settings.Toggles);
        context.Pipeline.Register(behavior, "Optionally skips handlers based on feature toggles");
    }
}

The configuration extension

This method extends the endpoint configuration to enable the feature toggle's feature and add the feature toggle settings to the configuration. These settings are returned to the caller for additional tweaking. The settings are also extracted by the feature toggle's feature and used to construct the feature toggle behavior (see above).

public static class FeatureToggleConfigurationExtensions
{
    public static FeatureToggleSettings EnableFeatureToggles(this EndpointConfiguration endpointConfiguration)
    {
        endpointConfiguration.EnableFeature<FeatureToggles>();
        return endpointConfiguration.GetSettings().GetOrCreate<FeatureToggleSettings>();
    }
}

The endpoint configuration

With all of these pieces in place, the endpoint configuration code can set up feature toggles. In this sample, only Handler2 meets the conditions set out by the feature toggle.

var toggles = endpointConfiguration.EnableFeatureToggles();
toggles.AddToggle(ctx => ctx.MessageHandler.HandlerType == typeof(Handler2));

Related Articles