[
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)