PDGGK opened a new pull request, #37341:
URL: https://github.com/apache/beam/pull/37341

   ## Description
   
   Fixes #37176
   
   The `parseAndThrow` method in `Call.java` was wrapping retryable exceptions 
(`UserCodeTimeoutException`, `UserCodeRemoteSystemException`) in a generic 
`UserCodeExecutionException`, which breaks the retry logic that depends on 
`exception.shouldRepeat()` returning true.
   
   ## Problem
   
   When user code throws a `UserCodeTimeoutException` or 
`UserCodeRemoteSystemException` (which have `shouldRepeat() = true`), the old 
implementation would wrap these in a generic `UserCodeExecutionException` 
(which has `shouldRepeat() = false`), causing the `Repeater` to not retry the 
operation as intended.
   
   ## Solution
   
   - Scan the full causal chain using Guava's `Throwables.getCausalChain()`
   - Preserve all specific retryable exception types 
(Quota/Timeout/RemoteSystem)
   - Prefer specific types over generic `UserCodeExecutionException` when both 
exist in the chain to prevent masking of retryable exceptions
   - Handle circular causal chains gracefully by catching 
`IllegalArgumentException`
   
   ## Changes
   
   ### Modified Files
   
   
**`sdks/java/io/rrio/src/main/java/org/apache/beam/io/requestresponse/Call.java`**
 (+31/-7 lines)
   - Added `Throwables` import for causal chain traversal
   - Rewrote `parseAndThrow` method to scan full exception chain
   - Added logic to prefer specific exception types over generic ones
   - Added circular reference handling
   
   
**`sdks/java/io/rrio/src/test/java/org/apache/beam/io/requestresponse/CallTest.java`**
 (+264/-2 lines)
   - Added 10 new unit tests covering various exception scenarios
   
   ## Testing
   
   Added comprehensive test coverage for:
   - ✅ Direct retryable exceptions (Timeout, RemoteSystem, Quota)
   - ✅ Nested exceptions wrapped in `UncheckedExecutionException`
   - ✅ Generic `UserCodeExecutionException` masking specific types (3 scenarios)
   - ✅ Triple-nested exceptions
   - ✅ Circular reference in causal chain
   - ✅ Non-UserCode exceptions (RuntimeException)
   
   **Test Results:**
   - `CallTest`: All tests passing
   - Full `rrio` test suite: 90 tasks passing ✅
   - Code formatting: `spotlessCheck` passing ✅
   
   ## Impact
   
   **Behavior Change:** Code that previously saw a generic 
`UserCodeExecutionException` may now see the specific subtype 
(`UserCodeTimeoutException`/`UserCodeRemoteSystemException`). This is the 
**intended fix** to restore proper retry behavior.
   
   **Performance:** Minimal impact - exception chain traversal only occurs on 
error paths.
   
   **Backwards Compatibility:** The change improves correctness. Any code that 
relied on exceptions being wrapped was working around a bug.
   
   ## Example
   
   **Before:**
   ```java
   // User code throws UserCodeTimeoutException
   throw new UserCodeTimeoutException("timeout");
   
   // parseAndThrow wraps it
   throw new UserCodeExecutionException(cause); // shouldRepeat() = false ❌
   
   // Repeater sees generic exception and doesn't retry
   ```
   
   **After:**
   ```java
   // User code throws UserCodeTimeoutException
   throw new UserCodeTimeoutException("timeout");
   
   // parseAndThrow preserves it
   throw (UserCodeTimeoutException) throwable; // shouldRepeat() = true ✅
   
   // Repeater sees timeout exception and retries
   ```
   
   ## Checklist
   
   - [x] Addresses issue #37176
   - [x] All retryable exceptions are preserved
   - [x] Circular references handled gracefully
   - [x] Generic exception masking prevented
   - [x] Comprehensive test coverage added (10 new tests)
   - [x] All existing tests pass
   - [x] Code formatting clean (spotless)
   - [x] No breaking changes to public API
   - [x] Commit message follows conventions


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to