[ 
https://issues.apache.org/jira/browse/CAMEL-26736?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Work on CAMEL-26736 started by shashank.
----------------------------------------
> camel-jpa - JpaKeyValueRepository putIfAbsent: the loser of an insert race 
> fails, two callers can win an expired entry, and reading an expired entry can 
> delete a live one
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-26736
>                 URL: https://issues.apache.org/jira/browse/CAMEL-26736
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-jpa
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> CAMEL-26708 fixes two patterns in {{JdbcKeyValueRepository}} (camel-sql). 
> {{JpaKeyValueRepository}} has the same two patterns; it is a different 
> module, so it was left out of that PR (apache/camel#29405).
> *putIfAbsent*: when {{persist}} + {{flush}} fails with a constraint violation 
> (another node inserted the key), the key is read again with {{findByKey}} in 
> the same transaction. The failed flush has marked that transaction for 
> rollback, so the commit fails and the losing caller gets an exception 
> ({{DataIntegrityViolationException}} with the Spring based 
> {{DefaultTransactionStrategy}}) instead of the value of the winner. When the 
> entry is expired, {{putIfAbsent}} updates it in place with {{merge}}; 
> {{KeyValueEntry}} has no {{@Version}}, so two nodes that both read the 
> expired entry both update it and both return {{null}}: both win, and 
> {{KeyValueIdempotentRepository.add}} lets the same message through on both.
> *Lazy expiry*: {{get}} (and {{contains}}, {{delete}}) finds an expired entry 
> and deletes it with {{entityManager.remove}}, which deletes by primary key. 
> If another node stored the key between the read and the delete, its live 
> entry is deleted.
> *Expected*: one winner per key across nodes, and an expired entry is deleted 
> only while it is still expired.
> *Suggested fix*, as in CAMEL-26708: let the constraint violation roll back 
> the transaction and read the key again in a new transaction (bounded 
> attempts), let the primary key decide for an expired entry as well (delete it 
> while it is still expired, then insert), and delete an expired entry with a 
> JPQL {{DELETE ... WHERE itemKey = ?1 AND expiresAt > 0 AND expiresAt <= ?2}} 
> instead of {{remove}}. Tests can use two repositories on one embedded 
> database, as {{JdbcKeyValueRepositoryConcurrencyTest}} in apache/camel#29405 
> does.
> *Affected*: main (reproduced with H2 and OpenJPA, two repositories on one 
> database) and 4.23.0 (read; the class is new in 4.23).
> _Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to