[ 
https://issues.apache.org/jira/browse/CAMEL-25709?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Work on CAMEL-25709 started by shashank.
----------------------------------------
> Aggregate EIP - a group is never completed by its completionTimeout, and 
> nothing is logged, when the aggregation repository fails once while the 
> timeout checker completes it
> -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25709
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25709
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> The completion timeout of the Aggregate EIP is driven by 
> {{AggregationTimeoutMap}}, a {{DefaultTimeoutMap}} that the timeout checker 
> purges every {{completionTimeoutCheckerInterval}} (1000 ms by default). 
> {{DefaultTimeoutMap.purge()}} first removes every expired entry from the map 
> and then calls the listeners; the aggregator's listener, 
> {{AggregationTimeoutMap.onEviction}}, reads the group from the aggregation 
> repository ({{aggregationRepository.get}}), removes it ({{onCompletion}} -> 
> {{aggregationRepository.remove}}) and sends it on.
> If the listener throws, {{DefaultTimeoutMap.emitEvent}} drops the exception 
> without a log line (main 07c54cb62eae, {{DefaultTimeoutMap.java:243-247}}: 
> {{catch (Exception t) { // Ignore }}}). The entry is already gone from the 
> timeout map, so nothing will ever try to complete that group again:
> * the group stays in the aggregation repository and is never sent, unless 
> another message with the same correlation key arrives (which puts a new 
> timeout entry) or the route is restarted (which rebuilds the timeout map from 
> the repository);
> * nothing is logged: neither the WARN of the purge task nor any other line.
> Only {{OptimisticLockingException}} is handled in {{onEviction}}. Any other 
> exception of the repository ends the group's timeout, for example a 
> {{JdbcAggregationRepository}} (camel-sql) whose database is not reachable for 
> a moment, or a Redis / Cassandra / Infinispan / Hazelcast repository with a 
> connection error at that time. CAMEL-24141 fixed the same failure mode for 
> the recover task and the completionInterval task, and stated that the 
> completionTimeout checker survives repository hiccups: the checker task does, 
> but the group whose timeout was being handled does not.
> Trigger: {{completionTimeout}} (or {{completionTimeoutExpression}}) with a 
> persistent aggregation repository, and one failing {{get}} or {{remove}} call 
> of that repository at the moment the group times out. When correlation keys 
> are not reused (an order id, a batch id), the group is lost for good while 
> the route keeps running.
> h3. Reproduction
> New {{AggregateTimeoutRepositoryExceptionTest}} (camel-core): a 
> {{MemoryAggregationRepository}} wrapper fails exactly once, in {{get}} or in 
> {{remove}}, on the call made by the timeout checker 
> ({{completionTimeout(200)}}, {{completionTimeoutCheckerInterval(50)}}). On 
> main both tests fail after 10 seconds:
> {noformat}
> mock://result Received message count. Expected: <1> but was: <0>
> {noformat}
> and the test log has no line about the simulated failure.
> h3. Proposed fix
> {{AggregationTimeoutMap.onEviction}} catches an exception of the completion, 
> logs a WARN (correlation key, cause; the stack trace at DEBUG) and puts the 
> key back into the timeout map to be tried again after 
> {{completionTimeoutCheckerInterval}}. It uses {{putIfAbsent}}, so a timeout 
> entry that a new message for the key put in the meantime is kept. When the 
> group had already been removed before the error (for example 
> {{AggregationStrategy.timeout}} threw), the next try finds no group and does 
> nothing, as for a group completed by another node.
> A group the repository can never read is now logged once per check interval 
> until it is removed, like the completionInterval and recover tasks log each 
> failing run. No option or default changes, so no upgrade guide entry.
> camel-core tests with the fix: 8185 run, 0 failures, 0 errors, 45 skipped. 
> Not run: camel-sql / camel-cassandraql / camel-redis repositories against a 
> real store.
> How it was found: a sweep of tasks scheduled on executors and timers whose 
> first exception ends them (after the camel-ibm-secrets-manager refresh task); 
> the aggregator's recover and interval tasks were guarded by CAMEL-24141, so 
> the timeout path was read next; {{emitEvent}} swallows listener exceptions 
> after the entry is removed. The test confirmed it.
> Affected: main (07c54cb62eae; tested). camel-4.23.x ({{onEviction}} line 
> 1579), camel-4.22.x (1352), camel-4.18.x (1308) and camel-4.14.x (1294) have 
> the same listener and the same {{emitEvent}} (read, not run).
> Duplicate check (2026-10-16): JIRA text "AggregationTimeoutMap", "onEviction 
> aggregate", "completionTimeout repository", "aggregator completionTimeout 
> never completes", "completion timeout repository exception", 
> "DefaultTimeoutMap listener exception ignored" (CAMEL-24141, CAMEL-24945, 
> CAMEL-25130, CAMEL-24943, CAMEL-24946, CAMEL-25095: none about an exception 
> in the timeout listener); GitHub pull requests "AggregationTimeoutMap", 
> "aggregate onEviction", "aggregate completion timeout repository", 
> "DefaultTimeoutMap listener" (#26790, #27033, #26788, #27039 and 
> reply-manager fixes; none about this).
> _Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to