- Shipped
- 25 Agosti 2026, 15:03 UTC
- Author
- Kamo
- Commit
- 2be051e
claimNextVersion is an UPDATE ... SET current_version_id = current_version_id + 1 and must be the FIRST statement of a write transaction. The obvious alternative — read the current version, add one, write — is a read-after-write inside one transaction, which YugabyteDB aborts with SQLSTATE 40001 under concurrency. It fails intermittently, so it presents as a random deadlock, and a retry loop appears to fix it while fixing nothing: the retry has the same shape and just wins the race more often. The UPDATE also takes the lock and reads in one round trip, which is one fewer than what it replaces. findClaimedVersion reads back in the same transaction and is safe despite that warning, because the UPDATE already took the row's lock — Yugabyte's read-restart problem is about rows another transaction may move under you. The resource lookup deliberately returns DELETED resources. A caller has to tell "never existed" (404) from "deleted" (410 Gone), and FHIR requires a deleted resource to keep answering vread and _history; filtering them here would make that impossible one layer up. FhirResourceVersionRepository declares NO delete and NO update, and a test enforces that it never gains one. The entity refuses both through @PreRemove/@PreUpdate — but those are ENTITY CALLBACKS, and a Spring Data derived delete compiles to bulk JPQL that bypasses them completely. Such a method would erase clinical history silently while the entity's own protection never fired. Not declaring one is the actual protection, and that is a decision no compiler enforces. History and reprojection reads are both paged, because an actively amended chart accumulates versions and an unbounded read is unbounded exactly where it hurts most. SharedLibBeanSafetyTest still passes: repositories are interfaces, and no stereotype bean was added to the library. 1655 tests green.