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]

Reply via email to