allthingssecurity opened a new pull request, #29195: URL: https://github.com/apache/camel/pull/29195
# Description [CAMEL-26579](https://issues.apache.org/jira/browse/CAMEL-26579) With the pooled exchange factory (deprecated since 4.23 but still supported; a consumer commit that never runs is worth fixing there), releasing a copy resets it (`DefaultPooledExchange.done()` -> `resetExtension()`), and the reset calls `reset()` on the unit of work the copy holds (CAMEL-24800 made more copies get reset when released). Some copies hold the unit of work of the exchange they were copied from, so the release resets the *parent's* unit of work while the parent is still routed: its synchronizations are cleared and its on completions (the commit or rollback of its consumer, route `onCompletion`) never run. The copies that hold the parent's unit of work when they are released: - the copy every Split makes to create its parts from (`SplitterIterable`, released in `close()`): a new pooled exchange is made with the copy constructor, which keeps the unit of work reference; - the parts of a Split, Multicast or Recipient List with `shareUnitOfWork` (released in `MulticastProcessor.doDone`; streamed parts are not released there); - the resource exchange of an Enrich with `shareUnitOfWork`. A released copy also kept that reference in the pool. And from the second message on, a Split with `shareUnitOfWork` takes the copy it creates the parts from out of the pool, where it does not hold the parent's unit of work, while the parts took the unit of work to share from that copy. ## The fix Before releasing such a copy, detach the parent's unit of work from it (`setUnitOfWork(null)`): - `SplitterIterable.close()`: always (the copy is only used to create the parts from and is never routed itself; no part is created after `close()`); - `MulticastProcessor.doDone`: a part whose unit of work is the parent's (`shareUnitOfWork`); - `Enricher`: the resource exchange when it shares the unit of work. The parts of a Split with `shareUnitOfWork` now share the unit of work of the exchange being split instead of that of the copy (the same object without pooling). A copy with a unit of work of its own is reset as before. Nothing changes without the pooled factories (the default exchange factory does not reset on release). ## Tests `PooledExchangeShareUnitOfWorkTest` (pooled factories): an on completion added by the first step of the route (as a consumer's commit) must run once after a split, a parallel split, a multicast, a recipient list and an enrich with `shareUnitOfWork`, a split without it, and a failing split (`onFailure` once), with nothing left in flight; and over two messages every part of a split with `shareUnitOfWork` must have the unit of work of its parent. A route without a split is the control. On main the cases fail (the on completion never runs); with the fix all pass, 20 times in a row, with the pooled, split, multicast, enrich and recipient list tests of camel-core. _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]
