allthingssecurity opened a new pull request, #26913: URL: https://github.com/apache/camel/pull/26913
# Description [CAMEL-25038](https://issues.apache.org/jira/browse/CAMEL-25038) `DisruptorProducer` waits for the reply the same way `SedaProducer` did before CAMEL-24947 and CAMEL-24948, and it has the same two bugs. The seda fixes (#26793, which is still open, and #26794, which is merged) only changed camel-seda. 1. **Late reply.** The reply path (`onDone`) checked `latch.getCount() == 0` and then copied the reply into the caller's exchange. That is not atomic with the timeout branch, which sets `ExchangeTimedOutException`, counts down and returns. A reply arriving at about the timeout could be returned together with `ExchangeTimedOutException`. It could also be copied into the caller's exchange after the producer had returned, and `copyResults` then clears the exception while the caller's error handler works on it. In a stress run, 25 of 400 near-timeout requests came back with the reply body and the timeout exception. 2. **Interrupt.** With `timeout=0`, an interrupted `latch.await()` was logged and otherwise swallowed. The caller got a successful exchange whose "reply" was its own request, and the real reply was written into the exchange later. This change applies the seda approach to `DisruptorProducer`: - The reply, the timeout and the interrupt claim the exchange with a compare-and-set on a shared `AtomicBoolean`. A reply that loses the claim is ignored. - A timeout that loses the claim means the reply is being copied, so the producer waits (uninterruptibly) for that short copy to finish and returns the reply. - An interrupted reply wait (`timeout=0`) that wins the claim fails the exchange with the `InterruptedException`, as seda does since CAMEL-24948. If it loses, it waits for the copy like the timeout does. The interrupt status is kept in both cases. - An interrupt during a wait with `timeout > 0` is still reported as a timeout, as in seda. - The upgrade guide (4.23) notes the change, next to the seda entry. The existing `DISRUPTOR_IGNORE_EXCHANGE` property is still set on the caller's exchange on timeout, which is an older bug that this PR leaves alone: every later copy of that exchange inherits it (for example on a redelivery after a timeout, or a `doCatch` fallback to another disruptor endpoint), and the disruptor consumer silently drops any exchange that carries it. So redeliveries after a first timeout always time out, and an InOnly fallback is lost. I'll raise that in its own JIRA. Tests, modelled on `SedaTimeoutLateReplyTest` and `SedaProducerInterruptedTest`: - `DisruptorTimeoutLateReplyTest` (3 tests) pauses the reply copy with a `SafeCopyProperty`, only when it is called from the producer's `onDone`, and lets the timeout or an interrupt happen during the copy. It also checks that a reply after the timeout is ignored. - `DisruptorProducerInterruptedTest` interrupts an InOut caller that waits without a timeout. There are no sleeps, and the waits use latches and Awaitility. Without the main-code change: ``` testReplyBeingCopiedWhenTimeoutOccurs Producer returned while the reply was copied into the exchange ==> expected: <false> but was: <true> testReplyBeingCopiedWhenInterrupted Producer returned while the reply was copied into the exchange ==> expected: <false> but was: <true> testInterruptedWhileWaitingForReply Unexpected null value, expected: <java.lang.InterruptedException> but was: <null> ``` (`testReplyAfterTimeoutIsIgnored` passes before and after; it guards the ignored late reply.) With the change, all camel-disruptor tests pass (106 tests, 0 failures), and `*Seda*` in camel-core passes too (142 tests, 0 failures). Found with the TLA+ model of the seda producer/consumer handshake, re-targeted to `DisruptorProducer`. The fixed variant satisfies `NoWriteAfterReturn`, `CallerViewStable`, `ConsistentOutcome` and `ProducerReturns`. I then reproduced both bugs against the real classes. # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built and tested the affected modules, including the formatter and import-sort plugins. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- 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]
