allthingssecurity opened a new pull request, #27032:
URL: https://github.com/apache/camel/pull/27032

   # Description
   
   [CAMEL-25123](https://issues.apache.org/jira/browse/CAMEL-25123)
   
   When the SEDA producer does not add an InOnly message to the queue, the on 
completions of the exchange never run. With a file consumer, the file is then 
neither committed nor rolled back, stays in the consumer's in-progress 
repository, and is not picked up again until a restart:
   
   ```
   from("file:in").to("seda:q?size=1&discardWhenFull=true");
   from("seda:q?size=1&discardWhenFull=true").delay(400).to("log:done");
   
   4 files: 1 consumed, 3 files left in "in" (not moved to .camel), in-progress 
repository size 3
   ```
   
   For an InOnly exchange, `SedaProducer.addToQueue` creates the copy with 
`prepareCopy(exchange, true)`, which hands the on completions of the exchange 
over to the copy (the file consumer's commit and rollback, `onCompletion` 
synchronizations, and the release of a spooled stream cache). When the copy is 
then not added to the queue, it is dropped together with them:
   - `discardWhenFull=true` and the queue is full: the exchange completes as a 
success, but the consumer never commits the message.
   - the queue is full (`Queue full`), the `offerTimeout` elapses, or the 
producer is interrupted: the exchange fails, but the consumer never rolls the 
message back, so it is not retried.
   - with stream caching spooled to disk, the spool file of the dropped copy is 
also left behind until the context stops.
   
   `DisruptorProducer` does the same when `doPublish` fails (the ring buffer is 
full with `blockWhenFull=false`, or the Disruptor is not started).
   
   This change:
   - `SedaProducer.addToQueue` hands the on completions of the copy back to the 
exchange (`target.getExchangeExtension().handoverCompletions(exchange)`) when 
the copy was not added to the queue, in a `finally`, so it covers the discard 
and every exception. The on completions then run when the exchange is done, 
with its outcome: a discarded message is committed, as the exchange completes 
as a success, and a message that could not be added is rolled back. The copy's 
own stream cache reference goes back with them, so its spool file is released. 
The enqueue branches moved unchanged into `offerToQueue`, which returns whether 
the copy was added.
   - `DisruptorProducer.process` does the same when `doPublish` throws for an 
InOnly exchange.
   - The InOut path (`copy=false`, the producer waits for the copy) is 
unchanged: nothing is handed over there.
   - Upgrade guide note for 4.23, as a discarded message is now committed by 
its consumer (for example the file is moved or deleted), where it used to stay 
in the input.
   
   This is the same kind of problem as CAMEL-24950 (the exchanges dropped by 
purging the queue), but there the queue had accepted the copy and the exchange 
that sent it had already completed, so the purge runs the on completions of the 
dropped copy as a failure itself. Here the copy never left the producer, so the 
on completions go back to the exchange and follow its outcome.
   
   Tests:
   - New `SedaQueueFullOnCompletionTest` (camel-core, where the seda tests 
live), with queues of size 1 that are full: `discardWhenFull` (the on 
completion of the discarded exchange runs `onComplete`), `offerTimeout` and a 
full queue (`onFailure`), a file consumer with `discardWhenFull` (the discarded 
file is moved to `.camel` at once, the queued one when the seda route runs), 
and a spooled stream with `discardWhenFull` (the spool directory is empty at 
the end).
   - New `DisruptorRingBufferFullOnCompletionTest` (camel-disruptor): a ring 
buffer of size 1 held by a blocked consumer, `blockWhenFull=false`: the second 
message fails and its on completion runs `onFailure`, and the first one 
completes when the consumer is released.
   - Without the change, all 5 seda tests fail (no on completion runs, the file 
stays in the input, a spool file is left behind), and the disruptor test fails 
(`expected: <[failure:B]> but was: <[]>`).
   - With the change: camel-core 
`org/apache/camel/component/seda/**,*Seda*,*StreamCach*,*Disruptor*,*WireTap*,*Multicast*`:
 378 tests, 0 failures, 0 errors. camel-disruptor, all tests: 116 tests, 0 
failures, 0 errors.
   
   This merges cleanly with main (including #26995, CAMEL-25094, in the same 
method).
   
   Found while reviewing the seda spool file fix (CAMEL-25094): a copy that 
`discardWhenFull` drops leaks its spool file, and the original exchange loses 
its on completions. I then reproduced it with a real file consumer as above, on 
main and with this change (discard: the 3 discarded files are committed; 
offerTimeout and a full queue: the 3 files are rolled back, retried, and all 4 
are consumed; no spool file left, and all on completions run).
   
   # 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