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]

Reply via email to