Skip to content

Message Expiration

Some messages you publish or send will be transient, or only be valid for only a brief time. In this case you may find it valuable to apply message expiration rules to tell Wolverine to ignore messages that are too old.

You won't use this explicitly very often, but this information is ultimately stored on the Wolverine Envelope with this property:

cs
/// <summary>
///     Instruct Wolverine to throw away this message if it is not successfully sent and processed
///     by the time specified
/// </summary>
public DateTimeOffset? DeliverBy
{
    get => _deliverBy;
    set => _deliverBy = value?.ToUniversalTime();
}

snippet source | anchor

At runtime, Wolverine will:

  1. Wolverine will discard received messages that are past their DeliverBy time
  2. Wolverine will also discard outgoing messages that are past their DeliverBy time
  3. For transports that support this (Rabbit MQ for example), Wolverine will try to pass the DeliverBy time into a transport's native message expiration capabilities

At Message Sending Time

On a message by message basis, you can explicitly set the deliver by time either as an absolute time or as a TimeSpan past now with this syntax:

cs
public async Task message_expiration(IMessageBus bus)
{
    // Disregard the message if it isn't sent and/or processed within 3 seconds from now
    await bus.SendAsync(new StatusUpdate("Okay"), new DeliveryOptions { DeliverWithin = 3.Seconds() });
    
    // Disregard the message if it isn't sent and/or processed by 3 PM today
    // but watch all the potentially harmful time zone issues in your real code that I'm ignoring here!
    await bus.SendAsync(new StatusUpdate("Okay"), new DeliveryOptions { DeliverBy = DateTime.Today.AddHours(15)});
}

snippet source | anchor

By Subscriber

The message expiration can be set as a rule for all messages sent to a specific subscribing endpoint as shown by this sample:

cs
using var host = await Host.CreateDefaultBuilder()
    .UseWolverine((context, opts) =>
    {
        // One way or another, you're probably pulling the Azure Service Bus
        // connection string out of configuration
        var azureServiceBusConnectionString = context
            .Configuration
            .GetConnectionString("azure-service-bus");

        // Connect to the broker in the simplest possible way
        opts.UseAzureServiceBus(azureServiceBusConnectionString).AutoProvision();

        // Explicitly configure a delivery expiration of 5 seconds
        // for a specific Azure Service Bus queue
        opts.PublishMessage<StatusUpdate>().ToAzureServiceBusQueue("transient")
            
            // If the messages are transient, it's likely that they should not be 
            // durably stored, so make things lighter in your system
            .BufferedInMemory()
            .DeliverWithin(5.Seconds());

    }).StartAsync();

snippet source | anchor

By Message Type

At the message type level, you can set message expiration rules with the Wolverine.Attributes.DeliverWithinAttribute attribute on the message type as in this sample:

cs
// The attribute directs Wolverine to send this message with 
// a "deliver within 5 seconds, or discard" directive
[DeliverWithin(5)]
public record AccountUpdated(Guid AccountId, decimal Balance);

snippet source | anchor

Released under the MIT License.