Expose session state on ServiceBusReceivedMessageContext#49850
Draft
EldertGrootenboer wants to merge 7 commits into
Draft
Expose session state on ServiceBusReceivedMessageContext#49850EldertGrootenboer wants to merge 7 commits into
EldertGrootenboer wants to merge 7 commits into
Conversation
Add getSessionState() and setSessionState(byte[]) to ServiceBusReceivedMessageContext so session state can be read and written from a ServiceBusSessionProcessorClient message handler without opening a separate session receiver. The methods throw IllegalStateException when the message was not received from a session-enabled entity. Resolves Azure#49207
|
Azure Pipelines: Successfully started running 1 pipeline(s). 34 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds synchronous session-state access to ServiceBusReceivedMessageContext, enabling session processors to read and write session state from within the message handler without creating a separate session receiver, addressing parity with .NET and resolving #49207.
Changes:
- Added public
getSessionState()/setSessionState(byte[])toServiceBusReceivedMessageContext, delegating to either the session processor’s tracked receiver or the underlying receiver client. - Implemented session-processor routing via
SessionsMessagePump.SessionReceiversTrackerand session-scoped management-node operations inServiceBusSessionReactorReceiver. - Added unit tests covering both delegation paths and error cases, and documented the feature in the module changelog.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| sdk/servicebus/azure-messaging-servicebus/src/main/java/com/azure/messaging/servicebus/ServiceBusReceivedMessageContext.java | Adds the new public session-state APIs and delegates to the appropriate underlying component. |
| sdk/servicebus/azure-messaging-servicebus/src/main/java/com/azure/messaging/servicebus/SessionsMessagePump.java | Adds session-state routing to the message’s session receiver via SessionReceiversTracker. |
| sdk/servicebus/azure-messaging-servicebus/src/main/java/com/azure/messaging/servicebus/ServiceBusSessionReactorReceiver.java | Implements session-state get/set using the session’s management node and link name. |
| sdk/servicebus/azure-messaging-servicebus/src/main/java/com/azure/messaging/servicebus/ServiceBusSessionAcquirer.java | Exposes the session management node accessor used for session-scoped operations. |
| sdk/servicebus/azure-messaging-servicebus/src/main/java/com/azure/messaging/servicebus/ServiceBusReceiverAsyncClient.java | Adds package-private message-scoped get/set session-state helpers used by the context. |
| sdk/servicebus/azure-messaging-servicebus/src/test/java/com/azure/messaging/servicebus/ServiceBusReceivedMessageContextTest.java | Adds unit tests validating delegation branches and error propagation behavior. |
| sdk/servicebus/azure-messaging-servicebus/src/test/java/com/azure/messaging/servicebus/SessionReceiversTrackerTest.java | Adds unit tests for tracker lookup, delegation, and error cases (including case-insensitive session-id lookup). |
| sdk/servicebus/azure-messaging-servicebus/CHANGELOG.md | Documents the new context APIs. |
Addresses PR review: emit a distinct IllegalStateException when a message has no session id (vs. an untracked session) in the session-processor path, guard the receiver-client session-state methods against a null session id (avoids an NPE from getLinkName), and document in the CHANGELOG that the context APIs also throw when the delivering session is no longer held.
Addresses PR re-review: ServiceBusReceivedMessage.getSessionId() may return an empty string; the session-processor path now routes an empty session id to the 'not a session-enabled entity' error instead of the misleading 'session is no longer active' error. Adds empty-session-id test coverage.
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
sdk/servicebus/azure-messaging-servicebus/src/main/java/com/azure/messaging/servicebus/ServiceBusReceiverAsyncClient.java:1905
getSessionState(String)has two issues: (1) emptysessionIdisn’t validated (it will be rejected later by the management channel with a different exception), and (2) the tracing span name is mistakenlyServiceBus.setSessionStateeven though this method callschannel.getSessionState(...). Add an empty-string guard and rename the trace operation toServiceBus.getSessionState.
private Mono<byte[]> getSessionState(String sessionId) {
if (isDisposed.get()) {
return monoError(LOGGER,
new IllegalStateException(String.format(INVALID_OPERATION_DISPOSED_RECEIVER, "getSessionState")));
} else if (!isSessionEnabled) {
return monoError(LOGGER, new IllegalStateException("Cannot get session state on a non-session receiver."));
} else if (sessionId == null) {
return monoError(LOGGER,
new IllegalStateException("Cannot get session state because the session id is null."));
}
assert sessionManager != null; // guaranteed to be non-null when isSessionEnabled is true.
final String linkName = sessionManager.getLinkName(sessionId);
return tracer
.traceMono("ServiceBus.setSessionState",
connectionProcessor.flatMap(connection -> connection.getManagementNode(entityPath, entityType))
.flatMap(channel -> channel.getSessionState(sessionId, linkName)))
.onErrorMap((err) -> mapError(err, ServiceBusErrorSource.RECEIVE));
… test assertions Addresses PR re-review: getSessionState/setSessionState on the receiver client now reject an empty session id (not just null) with a clear IllegalStateException; tests compare session-state bytes by content (assertArrayEquals / Arrays.equals) instead of reference identity.
Addresses PR re-review: the V2 session-processor session-state path now emits ServiceBus.getSessionState/setSessionState spans (the reactor receiver retains the tracer and wraps the management-node calls with traceMono), matching the receiver-client path; and corrects the getSessionState span name in ServiceBusReceiverAsyncClient (was mislabeled ServiceBus.setSessionState).
Addresses PR re-review: the session-processor session-state path now maps management-link failures to ServiceBusException (ServiceBusErrorSource.RECEIVE), matching the receiver-client path and the ServiceBusReceivedMessageContext Javadoc contract, so callers no longer observe a raw AmqpException.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Expose session state on
ServiceBusReceivedMessageContextResolves #49207
Summary
Adds
getSessionState()andsetSessionState(byte[])toServiceBusReceivedMessageContext, so an application can read and writesession state directly from a
ServiceBusSessionProcessorClientmessagehandler without opening a separate session receiver. This brings the Java
session processor to parity with .NET, whose
ProcessSessionMessageEventArgsalready exposesGetSessionStateAsync/SetSessionStateAsync.What changed
ServiceBusReceivedMessageContextbyte[] getSessionState()andvoid setSessionState(byte[])SessionsMessagePump.SessionReceiversTrackerIllegalStateExceptionif that session is no longer heldServiceBusSessionReactorReceiverbeginLockRenew)ServiceBusReceiverAsyncClientgetSessionState(message)/setSessionState(message, state)for the non-session/V1 pathServiceBusSessionAcquirer.SessiongetSessionManagement()accessorThe only new public surface is the two methods on
ServiceBusReceivedMessageContext; everything else is package-private.Behavior
ServiceBusReceivedMessageContextis shared by both session and non-sessionprocessors. On a non-session entity the new methods throw a clear
IllegalStateException(the underlying receiver's existing guard). On asession entity they target the message's own session, so they are correct
for a processor handling multiple concurrent sessions.
Testing
ServiceBusReceivedMessageContextTest(10 tests: both delegationbranches, get/set, empty→null, and non-session / session-not-active error
asymmetry pairs) and
SessionReceiversTrackerTest(6 tests: no-session /untracked →
IllegalStateException, delegation, case-insensitive lookup).a session processor read
nullinitial state, wrote state, and read it back.spotless,checkstyle, andrevapiclean.Notes for reviewers
This adds public API surface, so it needs API review / Architecture Board
sign-off. Opened as a draft pending that review. A usage sample snippet
can follow as a small addition if desired.