Skip to content

fix(escrow-service): idempotent arbitrate skip, penalize mismatch log, consistent save() return#64

Merged
RedAvocado22 merged 1 commit into
mainfrom
fix/escrow-arbitrate-penalize-and-save-consistency
Jul 6, 2026
Merged

fix(escrow-service): idempotent arbitrate skip, penalize mismatch log, consistent save() return#64
RedAvocado22 merged 1 commit into
mainfrom
fix/escrow-arbitrate-penalize-and-save-consistency

Conversation

@RedAvocado22

Copy link
Copy Markdown
Owner

Closes #52
Closes #53

#52 — ArbitrateEscrowUseCase / PenalizeEscrowUseCase minor cleanup

  • ArbitrateEscrowUseCase: added a skip-guard when status == ARBITRATED, same shape as the existing idempotency guards in ConfirmDepositUseCase/ReleaseEscrowUseCase/PenalizeEscrowUseCase. Previously a retried admin arbitrate request would fall through into EscrowAccount.arbitrate()'s own guard and throw IllegalStateException("This payment not fully locked yet.") — a confusing message for what's actually an idempotent-retry case.
  • PenalizeEscrowUseCase: when skipping an already-penalized account, now logs a warn if the incoming event's cancelledBy doesn't match the party that was actually penalized (derived from the stored status), so a data mismatch is visible for debugging instead of silently returning.

#53 — EscrowAccountRepositoryImpl.save() return-value inconsistency

save() returned mapper.toDomain(saved) — a freshly reconstituted object — instead of the account argument it had just mutated (domain events already drained from it). No current caller reuses the pre-save reference, but it's inconsistent with ContractRepositoryImpl.save() (contract-service), which returns the original object, and is a footgun if a future caller holds onto account after calling save(). Now returns account directly.

Test plan

  • Full escrow-service test suite passes

…, consistent save() return

- ArbitrateEscrowUseCase: skip idempotently (log + return) when already ARBITRATED,
  instead of letting the domain method throw a misleading "not fully locked yet"
  error on retry — mirrors the guard pattern already used in ConfirmDepositUseCase/
  ReleaseEscrowUseCase/PenalizeEscrowUseCase.
- PenalizeEscrowUseCase: when skipping an already-penalized account, warn if the
  incoming event's cancelledBy differs from the party actually penalized, so a
  data mismatch is visible instead of silently swallowed.
- EscrowAccountRepositoryImpl.save(): return the mutated `account` argument
  instead of reconstituting a new object via mapper.toDomain(saved). No caller
  currently reuses the pre-save reference, but returning a different object than
  the one passed in is a footgun for future callers and was inconsistent with
  ContractRepositoryImpl.save() in contract-service, which already returns the
  original object.
@RedAvocado22 RedAvocado22 merged commit 1676710 into main Jul 6, 2026
2 checks passed
@RedAvocado22 RedAvocado22 deleted the fix/escrow-arbitrate-penalize-and-save-consistency branch July 6, 2026 10:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant