PAR-102
Idempotent transfer retry races on the dedup check-then-insert (500 instead of replay)
Pre-existing (not introduced by the develop→main release; surfaced during the release audit of PR #11).
In TransferService.transfer, the idempotency path is check-then-act: findByDedupKey → if null, proceed to insertTxn. Two concurrent requests carrying the same Idempotency-Key (same source account) can both read null and both proceed; the second insert violates the client_dedup_key UNIQUE constraint and the request fails with a 500 instead of replaying the first transaction's response.
Not a money-safety issue — the UNIQUE constraint prevents the double-insert, so there's no double-spend; the loser just gets an error rather than the idempotent replay it asked for. Severity low (rare: requires truly simultaneous retries).
Fix options: catch the duplicate-key DataIntegrityViolationException on insert and re-run findByDedupKey → replayIdempotent (treat the constraint violation as "someone else won the race, replay theirs"); or take a short advisory lock keyed on the dedup hash around the check-insert. The catch-and-replay approach is smaller and matches the existing replay semantics.
Out of scope for the current release PR — the F2 idempotency-scoping commit only changed what the key is derived from, not the concurrency model.
Resources
- commitf5c76e2 Release treasury-rest-api 2.1.0 (PAR-39, PAR-102, PAR-116)MCCitiesNetwork/treasury-rest-api
- commit80275ab Replay idempotent transfers that race on the dedup insert (PAR-102)MCCitiesNetwork/treasury-rest-api
Comments
No comments yet.
Activity
- ParadauxIO linked a commit — Commit f5c76e2 — Release treasury-rest-api 2.1.0 (PAR-39, PAR-102, PAR-116)
- ParadauxIO linked a commit — Commit 80275ab — Replay idempotent transfers that race on the dedup insert (PAR-102)
- ParadauxIO changed status to Status → Done
- ParadauxIO linked a commit — Commit f5c76e2 — Release treasury-rest-api 2.1.0 (PAR-39, PAR-102, PAR-116)
- tesks changed status to Status → Pending Release
- ParadauxIO linked a commit — Commit 80275ab — Replay idempotent transfers that race on the dedup insert (PAR-102)
- tesks created the issue