allthingssecurity opened a new pull request, #29533: URL: https://github.com/apache/camel/pull/29533
# Description [CAMEL-26770](https://issues.apache.org/jira/browse/CAMEL-26770) Found by Claus Ibsen while reviewing #29437 (CAMEL-26743), where `JdbcOrphanLockAwareIdempotentRepository` had the same pattern for its keep-alive set. `JdbcCachedMessageIdRepository.add` put the key in its in-memory cache as soon as `super.add` returned, before the transaction that inserted the row committed. When the add joins a caller's transaction (a transacted route on the same `DataSourceTransactionManager`) and that transaction rolls back, the row is gone but the key stayed in the cache. `add()` and `contains()` answer from the cache first, so the redelivery of the same message was rejected as a duplicate, although the database has no row for it. CAMEL-24046 made `add()` cache the key only after the insert succeeded; this is the case where the insert succeeds and the caller's transaction then rolls back. Change: - In a transaction with synchronization, `add` caches the key in `afterCommit` of a `TransactionSynchronization`, so a rolled-back add is never cached. Without a transaction it is cached at once, as before. - A `remove` of the key, or `clear()`, later in the same transaction cancels the pending caching, so a key added and removed in one transaction is not cached either. - `remove` and `clear()` empty the cache before their delete, as before, and now also after it. On a database that locks rows, a `remove` on another thread can wait for the row lock of an uncommitted add; when that add commits it caches the key, and the delete then removes the row, so the key must be evicted again. (H2 does not block there, so this has no test.) - Without a caller's transaction, `super.add` runs and commits its own transaction, and `add` then caches the key at once, as before. With a caller's transaction on another transaction manager (JMS, for example), the repository's own transaction commits the row first, and the key is cached when the caller's transaction commits; if that one rolls back, the row stays and the key is not cached, which only costs a cache miss. - As in #29437, two cases still cache a rolled-back key, as before this PR: an add inside a savepoint (`PROPAGATION_NESTED`) that rolls back while the outer transaction commits, and a JTA transaction that Spring did not start (`afterCommit` runs when Spring's scope ends, before the JTA commit). Tests (H2, no Docker), `JdbcCachedMessageIdRepositoryTransactionTest`, with the repository's own `TransactionTemplate` as the caller's transaction: - an add in a transaction that rolls back is not a duplicate afterwards (`contains` is false, and the redelivery is added); - an add in a transaction that commits is not cached before the commit (`contains` counts a miss and reads the row) and is answered from the cache afterwards (the hit count goes up); - an add followed by a `remove`, or by `clear()`, in the same transaction is not cached; - a plain add is cached as before. Without the change, the rollback test fails (the key is a duplicate from the cache); the add-then-remove and add-then-clear tests guard the cancelling. With it 5/5 (20 of 20 runs), and all 31 JDBC idempotent repository tests of camel-sql pass (offline). # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it): [CAMEL-26770](https://issues.apache.org/jira/browse/CAMEL-26770). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built camel-sql with the formatter and import-sort plugins and ran its idempotent repository tests. No generated file changes. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
