Skip to content

Use explicit message settlement via ServiceBusMessageActions#43

Open
andreasohlund wants to merge 57 commits intomainfrom
explicit-message-settlement
Open

Use explicit message settlement via ServiceBusMessageActions#43
andreasohlund wants to merge 57 commits intomainfrom
explicit-message-settlement

Conversation

@andreasohlund
Copy link
Copy Markdown
Member

@andreasohlund andreasohlund commented Mar 19, 2026

This uses message actions to explicitly control message settlement, including the ability to DLQ messages and perform other advanced operations that are only available via the actions.

Design decisions

Auto generation of MessageID

If no message ID is present on the native service bus message or in the application properties, a new ID will be generated and used. This new ID is persisted, so that the same ID is used when the message is retried, ensuring that the message is not abandoned or deadlettered. This further lowers the bar for native integration.

Messages that fail to be completed will not be reprocessed

Similar to the ASB transport messages that succeed processing but fail when the message is being completed, they will be completed immediately on the next processing attempt to reduce duplicate processing.

NOTE: The message id's are stored in an in-memory LRU cache, so duplicate processing on scaled-out instances can still occur, so this does not replace the use of the Outbox

Align upconversion of message properties to headers with the ASB transport

The same message properties (ReplyTo, CorrelationId, and ContentType) as the transport are now upconverted to NServiceBus headers.

DLQ poison messages

Messages where extracting the body and the headers are now dead-lettered in the same way as the transport.

DLQ messages when OnError fails with a non-transient exception

Failures in onError that are not transient service bus exceptions will now result in the message being dead-lettered

Support explicit DLQ requests via recoverability action

The existing package had a .DoNotSendMessagesToErrorQueue option, which resulted in retrying until the max delivery count was reached. This option is replaced with support for explicitly requesting the message being processed to be dead-lettered via a new recoverability action:

configuration.Recoverability().CustomPolicy((_, context) =>
{
    if (context.ImmediateProcessingFailures < 3)
    {
        return RecoverabilityAction.ImmediateRetry();
    }

    return new DeadLetterMessage(context.Exception);
   //OR:return new DeadLetterMessage("Some reason", "Some description"); 
});

Remove support for the ASB transport legacy body format

With this being a new component, supporting the very old ASB transport format is no longer needed. Customers can use a behavior in the physical receive pipeline to transform the body to be compatible as needed:

 if (message.ApplicationProperties.TryGetValue(TransportEncodingHeader, out var value)
&& value.Equals("wcf/byte-array"))
{
    using var reader = XmlDictionaryReader.CreateBinaryReader(
          body.ToStream(), XmlDictionaryReaderQuotas.Max);
    var bodyBytes = (byte[])Deserializer.ReadObject(reader)!;
    return new BinaryData(bodyBytes);
}

@andreasohlund
Copy link
Copy Markdown
Member Author

@danielmarbach ready for a initial review, some todos left in code for us to discuss

@andreasohlund andreasohlund marked this pull request as ready for review March 24, 2026 12:57
@andreasohlund
Copy link
Copy Markdown
Member Author

@danielmarbach ready for final review

@andreasohlund
Copy link
Copy Markdown
Member Author

@DavidBoike adding you FYI so no need to go deep into this one, the description should give you a good overview

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants