Skip to content

fix(payment-service): fence the side-effects lease with an owner token (#19) - #200

Open
Yousefa7medmaher wants to merge 1 commit into
devfrom
fix/payment-lease-fencing
Open

Yousefa7medmaher wants to merge 1 commit into
devfrom
fix/payment-lease-fencing

Conversation

@Yousefa7medmaher

Copy link
Copy Markdown
Member

Summary

Payment side-effect leases are now ownership-safe (#19).

Closes #19.

Changes

  • One token per lease. Every acquisition of the side-effects lease generates a unique owner token, stored in payments."sideEffectsLeaseToken" (migration 005, nullable). acquireSideEffectsLease returns the token, or null when another holder has it.
  • Every lease-protected write needs it. Releasing the lease, markEventPublished and markOrderSynced take the token and only write WHERE "sideEffectsLeaseToken" = <own>.
  • Stale workers fail closed. A worker whose lease expired and was taken over can no longer release the new lease or overwrite its markers. It stops writing and returns the payment as the new holder leaves it.
  • Event ids unchanged. They stay deterministic, so an event the stale worker already published is re-published by the new holder with the same eventId, and consumers drop the duplicate.
  • Deploy-safe. A lease held during the deploy has no token and simply expires (30 s); the next holder gets one.

Docs: docs/services/payment-service.md ("Lease ownership").

Builds on #18 (#195), which fenced the PROCESSING claim the same way.

Test plan

  • Unit tests: 70 service tests, including:
    • a normal run writes both markers and releases with its own token;
    • a worker taken over during the publish writes no marker and leaves the new lease alone;
    • a worker taken over during the order update writes no sync marker;
    • the new holder finishes the job with the same eventId.
  • PostgreSQL 16 integration (PAYMENT_TEST_DATABASE_URL), 24 tests, including:
    • a new token on every acquisition;
    • a stale holder can't write either marker or release the current holder's lease, and the current holder still holds it;
    • the legacy-upgrade test applies migrations 004 and 005 and still matches the entity.
  • All 109 payment-service tests pass after rebasing on dev; tsc; lint shows 0 errors.
  • CI

🤖 Generated with Claude Code

#19)

Each acquisition of the side-effects lease gets its own token, stored as
sideEffectsLeaseToken. Releasing the lease and writing the published and
order-synced markers require the current token, so a worker whose lease
expired and was taken over writes nothing and leaves the new holder to
finish. Event ids stay deterministic, so a re-publish is deduplicated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: make payment side-effect leases ownership-safe

1 participant