Skip to content

Allow configuring ServiceBusProcessorOptions for Azure Service Bus listeners#3286

Closed
jorik wants to merge 1 commit into
JasperFx:mainfrom
jorik:asb-processor-options
Closed

Allow configuring ServiceBusProcessorOptions for Azure Service Bus listeners#3286
jorik wants to merge 1 commit into
JasperFx:mainfrom
jorik:asb-processor-options

Conversation

@jorik

@jorik jorik commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Motivation

The Azure Service Bus transport currently creates the inline listener's ServiceBusProcessor with no options, so ServiceBusProcessorOptions.MaxAutoLockRenewalDuration is stuck at the Azure SDK default of five minutes. Any inline handler that runs longer than five minutes loses the message lock. When Wolverine then tries to complete the message, AzureServiceBusEnvelope.CompleteAsync swallows the "The lock supplied is invalid" ServiceBusException, so the ack silently fails and Azure Service Bus redelivers the message — duplicate work until MaxDeliveryCount finally dead-letters it.

There was previously no way to configure the underlying ServiceBusProcessorOptions at all. Jeremy invited this contribution in #2112 (originally #2110): "adding the ability to configure the ServiceBusProcessor objects would be a simple pull request."

What this adds

A ConfigureProcessor(Action<ServiceBusProcessorOptions>) fluent method on both:

  • AzureServiceBusQueueListenerConfiguration.ConfigureProcessor(Action<ServiceBusProcessorOptions>)
  • AzureServiceBusSubscriptionListenerConfiguration.ConfigureProcessor(Action<ServiceBusProcessorOptions>)

The action is stored on the endpoint (AzureServiceBusEndpoint.ConfigureProcessor) following the existing ConfigureQueue(Action<CreateQueueOptions>) / DelayedEndpointConfiguration.add(...) pattern. It is applied when the inline ServiceBusProcessor is created for both the queue and topic-subscription paths in AzureServiceBusTransport.Listening.cs via a new BuildProcessorOptions helper.

Typical use — raising the lock-renewal window for long-running inline handlers:

opts.ListenToAzureServiceBusQueue("incoming")
    .ConfigureProcessor(o => o.MaxAutoLockRenewalDuration = TimeSpan.FromMinutes(30))
    .ProcessInline();

Honored vs. reserved properties

BuildProcessorOptions invokes the user callback first, then re-asserts ReceiveMode = ServiceBusReceiveMode.PeekLock. The inline listener (InlineAzureServiceBusListener) completes, defers, and dead letters messages against the message lock, so ReceiveAndDelete would break acknowledgement, deferral, and dead lettering. ReceiveMode is therefore the one property the transport reserves; every other ServiceBusProcessorOptions property (including MaxAutoLockRenewalDuration, PrefetchCount, MaxConcurrentCalls, AutoCompleteMessages, etc.) is honored as configured.

Scope

Scoped to the non-session inline processor paths. Session-based listeners (RequireSessions()) do not use a ServiceBusProcessor at all — they use AcceptNextSessionAsync plus a manual ServiceBusSessionReceiver loop (AzureServiceBusSessionListener / SessionSpecificListener), so ServiceBusProcessorOptions / ServiceBusSessionProcessorOptions don't apply there. Extending session configuration would be a separate change against a different code path and is intentionally left out.

Tests

Added configuring_processor_options.cs (broker-free config-level tests, following the existing AzureServiceBusTransportTests pattern):

  • the configured action is stored on the queue endpoint after delayed config is applied
  • the configured action is stored on the subscription endpoint
  • BuildProcessorOptions applies the configured action (MaxAutoLockRenewalDuration, PrefetchCount)
  • BuildProcessorOptions re-asserts PeekLock even when the user sets ReceiveAndDelete
  • BuildProcessorOptions produces valid PeekLock options when no action is configured

Ran locally on net10.0 (the full ASB integration suite needs the emulator/a live namespace, which I did not run):

  • new configuring_processor_options tests: 5 passed
  • existing broker-free AzureServiceBusTransportTests + AzureServiceBusEndpointUriTests: 27 passed
  • Wolverine.AzureServiceBus and Wolverine.AzureServiceBus.Tests both build clean (0 warnings, 0 errors)

Docs

Added a "Configuring the ServiceBusProcessor" section to docs/guide/messaging/transports/azureservicebus/listening.md with a MaxAutoLockRenewalDuration sample sourced from DocumentationSamples.cs (region sample_configuring_azure_service_bus_processor_options), plus a note on the reserved ReceiveMode and the session-listener exclusion. (I couldn't run mdsnippets locally — it isn't installed in the environment — so the snippet source line link may need a regen pass.)

🤖 Generated with Claude Code

@mysticmind mysticmind added this to the 6.17.0 milestone Jul 2, 2026

@mysticmind mysticmind left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@jeremydmiller

Copy link
Copy Markdown
Member

Thanks @jorik — this is great, and the feature is being merged. I've opened #3293 which supersedes this PR: it carries your commit verbatim (same authorship preserved) and adds one extra commit that pins Microsoft.OpenApi to the patched 2.7.5 to clear the newly-published NU1903 advisory (GHSA-v5pm-xwqc-g5wc) that was failing CI repo-wide on current main — unrelated to your change.

Closing in favor of #3293. Full credit to you for the ServiceBus processor options feature. 🙏

jeremydmiller added a commit that referenced this pull request Jul 5, 2026
Configure ServiceBusProcessorOptions for Azure Service Bus listeners (supersedes #3286)
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.

3 participants