Configure delayed retries

Component: NServiceBus
Nuget Package: NServiceBus (Version: 5.x)
Starting from NServiceBus Version 6 Delayed Retries Policy (formerly known as Second Level Retries Policy) has been deprecated in favor of the new custom Recoverability policy which allows much more control over the Recoverability behavior. This documentation shows how previous Delayed Retries Policies can be implemented with the new Recoverability Policy.
Delayed Retries cannot be used when transport transactions are disabled or Delayed Delivery is not available. For more information about transport transactions, refer to transport transaction. For more information about delayed delivery, refer to delayed-delivery.

Configuring Delayed Retries

Common Settings

  • Enabled: Turns the feature on and off. Default: true.
  • TimeIncrease: A time span after which the time between retries increases. Default: 10 seconds (00:00:10).
  • NumberOfRetries: Number of times Delayed Retries are performed. Default: 3.

Using app.config

To configure Delayed Retries, enable its configuration section:

<configSections>
  <section name="SecondLevelRetriesConfig"
           type="NServiceBus.Config.SecondLevelRetriesConfig, NServiceBus.Core"/>
  </configSections>
<SecondLevelRetriesConfig Enabled="true"
                          TimeIncrease="00:00:10"
                          NumberOfRetries="3" />

Through IProvideConfiguration

class ProvideConfiguration :
    IProvideConfiguration<SecondLevelRetriesConfig>
{
    public SecondLevelRetriesConfig GetConfiguration()
    {
        return new SecondLevelRetriesConfig
        {
            Enabled = true,
            NumberOfRetries = 2,
            TimeIncrease = TimeSpan.FromSeconds(10)
        };
    }
}

Through ConfigurationSource

public class ConfigurationSource :
    IConfigurationSource
{
    public T GetConfiguration<T>() where T : class, new()
    {
        if (typeof(T) == typeof(SecondLevelRetriesConfig))
        {
            var config = new SecondLevelRetriesConfig
            {
                Enabled = true,
                NumberOfRetries = 2,
                TimeIncrease = TimeSpan.FromSeconds(10)
            };

            return config as T;
        }

        // Respect app.config for other sections not defined in this method
        return ConfigurationManager.GetSection(typeof(T).Name) as T;
    }
}
busConfiguration.CustomConfigurationSource(new ConfigurationSource());

Disabling Delayed Retries through code

busConfiguration.DisableFeature<SecondLevelRetries>();

Custom Retry Policy

Custom retry logic can be configured based on headers or timing in code.

Applying a custom policy

var retriesSettings = busConfiguration.SecondLevelRetries();
retriesSettings.CustomRetryPolicy(MyCustomRetryPolicy);

Simple Policy

The following retry policy that will retry a message 3 times with a 5 second interval.

TimeSpan MyCustomRetryPolicy(TransportMessage transportMessage)
{
    // retry max 3 times
    if (NumberOfRetries(transportMessage) >= 3)
    {
        // sending back a TimeSpan.MinValue tells the
        // SecondLevelRetry not to retry this message
        return TimeSpan.MinValue;
    }

    return TimeSpan.FromSeconds(5);
}

static int NumberOfRetries(TransportMessage transportMessage)
{
    string value;
    var headers = transportMessage.Headers;
    if (headers.TryGetValue(Headers.Retries, out value))
    {
        return int.Parse(value);
    }
    return 0;
}

Exception based Policy

The following retry policy extends the previous policy with a custom handling logic for a specific exception.

TimeSpan MyCustomRetryPolicy(TransportMessage transportMessage)
{
    if (ExceptionType(transportMessage) == typeof(MyBusinessException).FullName)
    {
        // Do not retry for MyBusinessException
        return TimeSpan.MinValue;
    }

    if (NumberOfRetries(transportMessage) >= 3)
    {
        return TimeSpan.MinValue;
    }

    return TimeSpan.FromSeconds(5);
}
static int NumberOfRetries(TransportMessage transportMessage)
{
    string value;
    var headers = transportMessage.Headers;
    if (headers.TryGetValue(Headers.Retries, out value))
    {
        return int.Parse(value);
    }
    return 0;
}
static string ExceptionType(TransportMessage transportMessage)
{
    var headers = transportMessage.Headers;
    return headers["NServiceBus.ExceptionInfo.ExceptionType"];
}

Legacy .Retries message receiver

In Versions 5 and below, the Delayed Retries of NServiceBus used the [endpoint_name].Retries queue for persistent storage of messages to be retried. To prevent message loss when upgrading in Version 6, a dedicated .retries queue receiver is started if not explicitly disabled. It serves a purpose of forwarding messages from the .retries queue to the endpoint's main queue to be retried appropriately.

The receiver is needed only during the upgrade from Versions 5 and below and is not needed for new endpoints using Version 6. For details on upgrade process and how to safely disable the receiver refer to: Version 5 Upgrade Guide.

Letting the receiver run might have negative performance implications depending on the transport. For endpoints using SQL Server or Msmq Transports it will result in periodic polling to check for messages in the .retries queue.

The .Retries can be disabled via code using:

var recoverability = endpointConfiguration.Recoverability();
recoverability.DisableLegacyRetriesSatellite();
This configuration API will be obsoleted and removed in Version 7.

Samples


Last modified