Skip to content

GH-3533: ASB session-id pinning (5.x backport → 5.40.0) - #3544

Merged
jeremydmiller merged 2 commits into
5.0from
backport/3533-asb-session-ids-5.0
Jul 20, 2026
Merged

GH-3533: ASB session-id pinning (5.x backport → 5.40.0)#3544
jeremydmiller merged 2 commits into
5.0from
backport/3533-asb-session-ids-5.0

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Backport of #3534 (issue #3533) to the 5.0 maintenance line. Targets the 5.0 branch and bumps the version to 5.40.0 for a NuGet release.

What

Adds an opt-in ServiceBusSessionProcessor-based session listener so competing consumers on one shared Azure Service Bus queue/subscription can each be pinned to their own session id(s). On a shared entity the session id becomes a broker-enforced routing key — a listener pinned to "A" never sees the messages meant for "B".

// Consumer node "A"
opts.ListenToAzureServiceBusQueue("shared-orders")
    .RequireSessionsWithOnlyTheseIdentifiers("A");

// Consumer node "B"
opts.ListenToAzureServiceBusQueue("shared-orders")
    .RequireSessionsWithOnlyTheseIdentifiers("B");

// Producer routes with the session id
await bus.PublishAsync(new OrderPlaced(...), new DeliveryOptions { GroupId = "A" }); // only A receives

Plus the general ConfigureSessionProcessor(Action<ServiceBusSessionProcessorOptions>) hook (multicast) on both queue and subscription listener configs.

Gating / safety

The existing hand-rolled AcceptNextSession loop remains the default; the processor engine only engages when ConfigureSessionProcessor is set (directly or via RequireSessionsWithOnlyTheseIdentifiers). Existing session listeners are untouched. Wolverine reserves ReceiveMode = PeekLock and AutoCompleteMessages = false.

Backport notes

Adapted to the 5.0 code shape, which differs from 6.x:

  • 5.0 has no ConfigureProcessor, no IReportConnectionState/AzureServiceBusConnectionStateMapper, and no endpoint PrefetchCount — so the new listener and BuildSessionProcessorOptions are written to the leaner 5.0 shape (session processor options carry no prefetch).
  • No conditional compilation needed for net8.0: ServiceBusSessionProcessor, ServiceBusSessionProcessorOptions, CreateSessionProcessor, and ProcessSessionMessageEventArgs are all in Azure.Messaging.ServiceBus regardless of target framework. The project builds clean on net8.0;net9.0;net10.0.

Tests

  • Unit coverage for BuildSessionProcessorOptions + both fluent methods.
  • An emulator end-to-end test reproducing the issue (listener pinned to "A" receives exactly its messages; a seeded "B" message stays undelivered on the shared queue).

All 8 tests green on net9.0 against the Azure Service Bus emulator; full ASB project builds clean on all three TFMs.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FKAxzuZ36VP6UPcTQf3MUs

…identifiers (5.x backport)

Backport of the 6.x change to the 5.0 maintenance line, bumped to 5.40.0.

Add an opt-in ServiceBusSessionProcessor-based session listener so competing
consumers on ONE shared queue/subscription can each be pinned to their own
session id(s). On a shared entity the session id becomes a broker-enforced
routing key, so a listener pinned to "A" never sees the messages meant for "B".

- ConfigureSessionProcessor(Action<ServiceBusSessionProcessorOptions>) on both
  queue and subscription listener configs (multicast, so it composes)
- RequireSessionsWithOnlyTheseIdentifiers(params string[]) sugar that populates
  ServiceBusSessionProcessorOptions.SessionIds
- BuildSessionProcessorOptions maps ListenerCount -> MaxConcurrentSessions,
  keeps in-session FIFO, and reserves ReceiveMode=PeekLock /
  AutoCompleteMessages=false
- New InlineAzureServiceBusSessionListener; AzureServiceBusEnvelope gains a
  ProcessSessionMessageEventArgs complete/defer/dead-letter path

Gated: the legacy AcceptNextSession loop stays the default and only flips to the
processor when ConfigureSessionProcessor is set, so existing session listeners
are unaffected. Adapted to the 5.0 code shape (no ConfigureProcessor /
IReportConnectionState / PrefetchCount that exist on 6.x). No conditional
compilation needed: the Azure SDK session-processor APIs are available on
net8.0/net9.0/net10.0. Unit tests + an emulator end-to-end test reproducing the
issue, all green on net9.0; full project builds clean on all three TFMs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKAxzuZ36VP6UPcTQf3MUs
@jeremydmiller
jeremydmiller merged commit ea0d0c6 into 5.0 Jul 20, 2026
21 of 23 checks passed
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.

1 participant