You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "shashank (Jira)" <ji...@apache.org> on 2026/10/16 12:08:00 UTC
[jira] [Created] (CAMEL-25709) 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
shashank created CAMEL-25709:
--------------------------------
Summary: 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
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)