shashank created CAMEL-26739:
--------------------------------

             Summary: camel-core - Aggregate EIP: a group completed by its 
first exchange is confirmed although it was never stored, and with 
JdbcAggregationRepository its id is kept for good
                 Key: CAMEL-26739
                 URL: https://issues.apache.org/jira/browse/CAMEL-26739
             Project: Camel
          Issue Type: Bug
          Components: camel-core, camel-sql
            Reporter: shashank
            Assignee: shashank


A group can be completed by the exchange that creates it, for example with 
{{completionSize(1)}}, or with a completion predicate that is true for a group 
of one exchange. Such a group is never added to the repository, so 
{{AggregateProcessor.doOnCompletion}} does not call {{remove()}} ("only remove 
if we have previous added"), and a recoverable repository has nothing in its 
completed store for it.

After the exchange is delivered, {{AggregateOnCompletion.onComplete}} still 
calls {{confirmWithResult}}. {{JdbcAggregationRepository}} finds no row, logs 
{{problem removing row ... DELETE statement did not return 1 but 0}} at ERROR, 
and returns {{false}}, so the exchange id is added to 
{{unconfirmedCompleteExchanges}}. That set was added in CAMEL-17613 to retry a 
confirm whose completed row is not visible yet. Only the recover task removes 
ids from it, and only ids it finds in the completed table, so these ids are 
never removed: not by later scans, nor by a route stop and start. The set grows 
by one id per such group (about 115 bytes of heap each) until the route is 
removed, and every such delivery logs a false ERROR.

Found with a TLA+ model of the Aggregate EIP with a recoverable repository. 
Short trace: a message arrives, the group has no stored exchange and is 
complete, the exchange is submitted and delivered, its confirm finds no 
completed row, and its id stays in the unconfirmed set. A route with 
{{aggregate(header("id"), 
strategy).aggregationRepository(jdbcRepo).completionSize(1)}} on H2 shows it: 
500 groups delivered, 500 ERROR lines, 500 ids kept through 15 recover scans 
and a route restart; with a 64 MB heap, about 400,000 such groups end in 
OutOfMemoryError. Groups of two exchanges keep no id.

Expected: a group that was never stored is not confirmed, so no ERROR is logged 
and no id is kept.

Suggested fix: mark the aggregated exchange of a group that was never stored in 
{{doOnCompletion}}, and skip the confirm for it in {{AggregateOnCompletion}}. 
Groups that were stored, and recovered exchanges, are confirmed as before.

_Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to