Wrap gRPC StatusRuntimeException across all DurableTaskGrpcClient methods#278
Wrap gRPC StatusRuntimeException across all DurableTaskGrpcClient methods#278
Conversation
Agent-Logs-Url: https://github.com/microsoft/durabletask-java/sessions/6c71e4a3-6ba6-4f7c-b5fb-038b059128d0 Co-authored-by: bachuv <15795068+bachuv@users.noreply.github.com>
…hods Add StatusRuntimeExceptionHelper to translate gRPC StatusRuntimeException into SDK-level exceptions: - CANCELLED -> CancellationException - DEADLINE_EXCEEDED -> TimeoutException (for checked exception variant) - Other codes -> RuntimeException with descriptive message Wrap all previously-unwrapped gRPC calls in DurableTaskGrpcClient: - scheduleNewOrchestrationInstance, raiseEvent, getInstanceMetadata - terminate, queryInstances, createTaskHub, deleteTaskHub - purgeInstance, suspendInstance, resumeInstance Update partially-wrapped methods to use helper as fallback: - waitForInstanceStart, waitForInstanceCompletion, purgeInstances, rewindInstance Add comprehensive unit tests for StatusRuntimeExceptionHelper. Agent-Logs-Url: https://github.com/microsoft/durabletask-java/sessions/6c71e4a3-6ba6-4f7c-b5fb-038b059128d0 Co-authored-by: bachuv <15795068+bachuv@users.noreply.github.com>
…downloadProtoFiles) Agent-Logs-Url: https://github.com/microsoft/durabletask-java/sessions/6c71e4a3-6ba6-4f7c-b5fb-038b059128d0 Co-authored-by: bachuv <15795068+bachuv@users.noreply.github.com>
|
@copilot - address the following feedback
|
1. Null-safe description: getDescriptionOrDefault() returns "(no description)" instead of letting null propagate into error messages. 2. Javadoc comment on toException explaining DEADLINE_EXCEEDED is included for completeness/future-proofing even though current call sites handle it first. 3. Extracted private helpers (createCancellationException, createRuntimeException, formatMessage, getDescriptionOrDefault) to eliminate duplication between toRuntimeException and toException. 4. Consistent message format: DEADLINE_EXCEEDED now uses the same "failed with a <code> gRPC status: <description>" prefix as all other status codes. Agent-Logs-Url: https://github.com/microsoft/durabletask-java/sessions/747c79d2-a3fa-427c-8b3d-63515878b1d1 Co-authored-by: bachuv <15795068+bachuv@users.noreply.github.com>
All four items addressed in a2d7c00:
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot - work on these changes Please update Required status mappings
Additional requirements
Tests to add/update
|
New gRPC status code → Java exception mappings: - INVALID_ARGUMENT → IllegalArgumentException - FAILED_PRECONDITION → IllegalStateException - NOT_FOUND → NoSuchElementException - UNIMPLEMENTED → UnsupportedOperationException All mapped exceptions include the Status.Code in the message, preserve the original StatusRuntimeException as cause, and handle null descriptions. Both toRuntimeException and toException support all new mappings. Tests added for each new mapping in both helper paths. Agent-Logs-Url: https://github.com/microsoft/durabletask-java/sessions/ea332218-fd02-4338-8805-e40f0009eb55 Co-authored-by: bachuv <15795068+bachuv@users.noreply.github.com>
Agent-Logs-Url: https://github.com/microsoft/durabletask-java/sessions/ea332218-fd02-4338-8805-e40f0009eb55 Co-authored-by: bachuv <15795068+bachuv@users.noreply.github.com>
Done in 42765bc. Added all requested mappings to both
All mapped exceptions include Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot - make this change
|
…rInstanceCompletion, purgeInstances Update rethrow logic after toException translation to check TimeoutException first, then RuntimeException, with defensive fallback as last resort. Agent-Logs-Url: https://github.com/microsoft/durabletask-java/sessions/2852d301-7a07-419c-a4f5-036184610079 Co-authored-by: bachuv <15795068+bachuv@users.noreply.github.com>
Updated in 539916b. All three methods now rethrow in the requested order: Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot - update the PR to add more tests Client-level unit tests (DurableTaskGrpcClient) with mocked sidecar stub
1. Newly wrapped methods
2. Updated timeout-declaring methods
3. Updated methods non-timeout status passthrough via helper
4. Existing special-case method (
|
Uses gRPC in-process transport with fake service implementations to verify each client method catches StatusRuntimeException and rethrows the correct translated SDK exception. Tests cover: - All newly wrapped methods (scheduleNewOrchestrationInstance, raiseEvent, getInstanceMetadata, terminate, queryInstances, createTaskHub, deleteTaskHub, purgeInstance, suspendInstance, resumeInstance) - Timeout-declaring methods with DEADLINE_EXCEEDED (waitForInstanceStart, waitForInstanceCompletion, purgeInstances) - Non-timeout status passthrough for timeout-declaring methods - rewindInstance special-case behavior (custom messages for NOT_FOUND, FAILED_PRECONDITION; helper fallback for UNAVAILABLE) - Contract assertions (exception type, gRPC cause preserved, message contains operation name and status code) Agent-Logs-Url: https://github.com/microsoft/durabletask-java/sessions/c4d58a2b-9982-49e3-bc9d-0b8527119032 Co-authored-by: bachuv <15795068+bachuv@users.noreply.github.com>
…n tests Agent-Logs-Url: https://github.com/microsoft/durabletask-java/sessions/c4d58a2b-9982-49e3-bc9d-0b8527119032 Co-authored-by: bachuv <15795068+bachuv@users.noreply.github.com>
... Added in d0241fb and 54035e4. Created Covered:
Integration tests are not included — they require a real sidecar/emulator which isn't available in the unit test suite. Those would need the Added Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Issue describing the changes in this PR
Most
DurableTaskGrpcClientmethods let rawio.grpc.StatusRuntimeExceptionescape to callers. This PR translates gRPC transport exceptions into SDK-level exceptions so callers don't depend on gRPC types directly.New utility:
StatusRuntimeExceptionHelperMaps gRPC status codes to Java-standard exception types:
CANCELLED→CancellationException(matches .NET'sOperationCanceledException)DEADLINE_EXCEEDED→TimeoutException(checked exception variant viatoExceptionfor methods that declare it)INVALID_ARGUMENT→IllegalArgumentExceptionFAILED_PRECONDITION→IllegalStateExceptionNOT_FOUND→NoSuchElementExceptionUNIMPLEMENTED→UnsupportedOperationExceptionRuntimeExceptionwith status code and description in the messageAdditional behavior:
Status.Codeincluded in all exception messagesStatusRuntimeExceptionpreserved as cause on all translated exceptions"(no description)"fallback whenStatus.getDescription()is null"The <op> operation failed with a <code> gRPC status: <description>"createCancellationException,createNoSuchElementException,formatMessage,getDescriptionOrDefault)Wrapped methods (previously no wrapping):
scheduleNewOrchestrationInstance,raiseEvent,getInstanceMetadata,terminatequeryInstances,createTaskHub,deleteTaskHub,purgeInstancesuspendInstance,resumeInstanceUpdated methods (had partial wrapping, now fall through to helper instead of re-throwing raw
StatusRuntimeException):waitForInstanceStart,waitForInstanceCompletion,purgeInstances,rewindInstanceTimeoutException→RuntimeException(preserving specific subtypes likeIllegalArgumentException,IllegalStateException, etc.) → defensiveRuntimeExceptionfallbackClient-level unit tests (
DurableTaskGrpcClientTest)Added 27 client-level unit tests using gRPC in-process transport (
grpc-inprocess) with fakeTaskHubSidecarServiceImplBaseimplementations to verify call-site wiring. Tests are organized in 5 sections:scheduleNewOrchestrationInstance→INVALID_ARGUMENT→IllegalArgumentException)DEADLINE_EXCEEDED(3 tests):waitForInstanceStart,waitForInstanceCompletion,purgeInstancesall throwTimeoutExceptionINVALID_ARGUMENT→IllegalArgumentException)rewindInstancespecial cases (3 tests): Custom messages forFAILED_PRECONDITION/NOT_FOUNDpreserved,UNAVAILABLEfalls through to helperNot changed:
GrpcDurableEntityClient— does not exist in this repo yetDurableTaskGrpcWorkercompletion calls — these are internal to the worker retry loop which already catchesStatusRuntimeExceptionat the outer level; wrapping them would bypass the retry/reconnection logicPull request checklist
CHANGELOG.mdAdditional information
Example of the wrapping pattern applied to each method:
For methods declaring
throws TimeoutException(waitForInstanceStart,waitForInstanceCompletion,purgeInstances), translated exceptions are rethrown with proper type preservation:Helper-level tests (
StatusRuntimeExceptionHelperTest) cover each status code mapping in bothtoRuntimeExceptionandtoExceptionpaths, including null description fallback and cause preservation.Client-level tests (
DurableTaskGrpcClientTest) use gRPC in-process transport with fake service implementations to verify each method's try/catch wiring end-to-end. Note: gRPC in-process transport recreatesStatusRuntimeExceptionobjects, so cause assertions verify status code equality rather than object identity.New test dependency:
io.grpc:grpc-inprocessadded toclient/build.gradle(test scope only, same version as existing gRPC dependencies).