[
https://issues.apache.org/jira/browse/CAMEL-24048?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Federico Mariani updated CAMEL-24048:
-------------------------------------
Attachment: JdbcAggregationRepositoryStaleRemoveTest.java
> camel-sql - stale remove() silently completes in JdbcAggregationRepository;
> idempotent add() leaks DuplicateKeyException; TokenMgrError escapes stored
> template parser
> ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: CAMEL-24048
> URL: https://issues.apache.org/jira/browse/CAMEL-24048
> Project: Camel
> Issue Type: Bug
> Components: camel-sql
> Reporter: Federico Mariani
> Priority: Major
> Attachments: JdbcAggregationRepositoryStaleRemoveTest.java,
> JdbcMessageIdRepositoryDuplicateInsertRaceTest.java,
> TemplateParserLexicalErrorTest.java
>
>
> Three correctness defects found during a camel-sql review, each with a
> deterministic reproducer test attached (all fail on current main, must pass
> after the fix):
> *1. JdbcAggregationRepository.remove() ignores the optimistic delete count*
> {{remove()}} deletes with {{WHERE id = ? AND version = ?}} but discards the
> update count. With a stale version (a concurrent add on another node bumped
> it), 0 rows are deleted, yet the stale aggregated exchange is still inserted
> into the completed table and {{remove()}} reports success: the live
> aggregation survives and completes again later (duplicate downstream
> delivery) while a bogus completed entry also exists. A 0-count delete should
> raise {{OptimisticLockingException}}, symmetric with {{updateHelper()}}. Same
> pattern in {{ClusteredJdbcAggregationRepository.remove()}}.
> Reproducer: JdbcAggregationRepositoryStaleRemoveTest.java
> *2. AbstractJdbcMessageIdRepository.add() propagates DuplicateKeyException on
> a cross-node insert race*
> {{add()}} is check-then-act (count, then insert). When a competing node
> inserts the same key between the two statements, the primary-key violation
> escapes {{add()}} as a raw Spring {{DuplicateKeyException}} and fails the
> exchange, instead of being treated as "already processed" (return false, like
> the plain count!=0 case). Idempotency itself holds, but the losing exchange
> goes to redelivery/DLQ. Care is needed not to mask rollback-only state when
> {{add()}} joins a caller's transaction ({{PROPAGATION_REQUIRED}} is a
> documented feature).
> Reproducer: JdbcMessageIdRepositoryDuplicateInsertRaceTest.java (simulates
> the race deterministically with a DataSource wrapper)
> *3. sql-stored: lexical errors escape as java.lang.Error*
> {{TemplateParser.parseTemplate()}} only catches {{ParseException}}, but the
> generated JavaCC lexer throws {{TokenMgrError}} - an {{Error}} - for any
> character outside the token alphabet (e.g. {{;}}). With
> {{useMessageBodyForTemplate=true}} or the {{CamelSqlStoredTemplate}} header
> the template comes from message content, so a stray character raises a raw
> {{Error}} in the route that {{onException}} handlers never see. Lexical
> errors should be wrapped in {{ParseRuntimeException}} like parse errors are.
> Reproducer: TemplateParserLexicalErrorTest.java
--
This message was sent by Atlassian Jira
(v8.20.10#820010)