[ 
https://issues.apache.org/jira/browse/CAMEL-25094?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18120122#comment-18120122
 ] 

shashank commented on CAMEL-25094:
----------------------------------

PR: https://github.com/apache/camel/pull/26995

I cannot assign issues to myself; could a committer assign this to me 
(smjainblr)? Thanks.

_Claude Code on behalf of allthingssecurity_

> camel-seda, camel-disruptor - a message sent InOnly to seda: or disruptor: 
> from inside a Multicast or Split loses its spooled stream cache file when the 
> parent exchange completes
> ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25094
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25094
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-disruptor, camel-seda
>            Reporter: shashank
>            Priority: Minor
>
> With stream caching spooled to disk ({{spoolEnabled=true}} and a body over 
> the spool threshold), the body is a {{FileInputStreamCache}}. Its temporary 
> file is deleted when the last exchange that holds it is done: 
> {{FileInputStreamCache.TempFileManager}} counts one for every {{addExchange}} 
> (the creation, and every {{StreamCache.copy(exchange)}}) and registers the 
> matching countdown as an on completion ({{FileInputStreamCache.java:255}}). 
> If the exchange has the property {{CamelStreamCacheUnitOfWork}}, the 
> countdown is registered on that unit of work instead of on the exchange.
> Multicast and Split set {{CamelStreamCacheUnitOfWork}} to the parent's unit 
> of work on every sub-exchange ({{MulticastProcessor.java:1127-1129}}, 
> {{Splitter.java:415-416}}), so that the stream caches of the sub-routes live 
> until the parent has aggregated them.
> A sub-exchange that sends to {{seda:}} without waiting for a reply (InOnly) 
> hands a copy to the queue. {{SedaProducer.addToQueue}} creates the copy and, 
> since CAMEL-20866 (4.7), gives it its own reference to the stream cache with 
> {{sc.copy(target)}} ({{SedaProducer.java:227}}). The copy keeps 
> {{CamelStreamCacheUnitOfWork}}, so that reference is registered on the 
> parent's unit of work as well. The InOnly send returns at once, the parent 
> finishes, its unit of work counts down both references and the file is 
> deleted. The seda consumer then routes the copy and fails:
> {noformat}
> WARN SedaConsumer - Error processing exchange. Exchange[]. Caused by:
>   [org.apache.camel.StreamCacheException - Error during type conversion from 
> type: null to the required type:
>    org.apache.camel.StreamCache due to 
> org.apache.camel.RuntimeCamelException: Cannot reset stream from file ...]
> {noformat}
> The seda route never gets past its start, so the message is lost after the 
> parent was told that it was sent. {{SedaConsumer}} logs the failure at WARN, 
> as above. {{DisruptorProducer.prepareCopy}} ({{DisruptorProducer.java:234}}) 
> does the same for {{disruptor:}}, and there the failure is not logged at all: 
> the disruptor consumer processes the exchange with a no-op callback, so the 
> message disappears without a log line.
> The Wire Tap EIP had exactly this problem and removes the property from its 
> copy ({{WireTapProcessor.java:282}}, CAMEL-12108). In CAMEL-20866, SEDA 
> (InOnly), Disruptor (InOnly) and Wire Tap were named as the cases where the 
> copied exchange is executed independently, but only the Wire Tap drops the 
> property.
> h3. Reproduction
> Stream caching with {{spoolEnabled=true}} and a small {{spoolThreshold}}, the 
> body is a stream of 16 KB. The seda (or disruptor) route waits until the 
> caller's {{sendBody}} has returned, so the parent exchange is done, and then 
> reads the body.
> || route || main ||
> | {{multicast().to("seda:b", "mock:other")}} | fails every time, as above |
> | {{multicast().parallelProcessing().to("seda:b", "mock:other")}} | fails 
> every time |
> | {{split(body()).to("direct:part")}} with 
> {{from("direct:part").to("seda:b")}} (the parts are streams) | fails every 
> time |
> | the same three with {{disruptor:b}} | fail every time, nothing is logged |
> | {{to("seda:b")}} or {{to("disruptor:b")}} without a Multicast or Split 
> (control) | works |
> | {{recipientList(constant("seda:b,mock:other"))}} (control) | works: the 
> Recipient List creates its own sub-exchanges and does not set the property |
> The wait in the seda route is not needed to trigger the failure: without it 
> the multicast case still failed in 20 of 20 runs, because the parent always 
> finishes first. The multicast case fails in the same way with the 4.6.0 
> {{SedaProducer}} (before the deep copy of CAMEL-20866): there the copy shares 
> the parent's cache, whose file the parent's unit of work deletes. So this is 
> not a regression of CAMEL-20866.
> A TLA+ model of the counter (parent, sub-exchange, seda copy, seda consumer) 
> finds the same trace (send to seda, parent done, consumer reads a deleted 
> file). The model without a Multicast and the model of the fix below hold, 
> including that the file is always deleted in the end.
> h3. Proposed fix
> In {{SedaProducer.addToQueue}} and {{DisruptorProducer.prepareCopy}}, in the 
> branch that copies the exchange, remove 
> {{ExchangePropertyKey.STREAM_CACHE_UNIT_OF_WORK}} from the copy before 
> {{sc.copy(target)}}, as the Wire Tap does. The copy then releases the file 
> when it is done itself. The path that waits for a reply (InOut, 
> {{waitForTaskToComplete}}) is not changed, because the producer waits for the 
> copy there. With this change all the failing cases above read the full body, 
> and no spool file is left behind afterwards. camel-stub extends 
> {{SedaProducer}} and gets the same fix.
> Affected: long-standing, all 4.x versions (checked on main and with the 4.6.0 
> {{SedaProducer}}).
> Duplicate check (2026-09-28): JIRA text "Cannot reset stream from file" 
> (CAMEL-21162, CAMEL-12108, CAMEL-12067, CAMEL-8688), 
> "CamelStreamCacheUnitOfWork" (CAMEL-12108, CAMEL-13168 for direct-vm), 
> "spool" with seda or disruptor: none about seda or disruptor. GitHub pull 
> requests on "StreamCache", "spool", "FileInputStreamCache", 
> "STREAM_CACHE_UNIT_OF_WORK": #14502 (CAMEL-20866) and CAMEL-25004 (stream 
> caching strategy lifecycle), not this.
> _Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to