Skip to content

fix(checkout-api): resolve checkout-race-condition#19

Open
Spkap wants to merge 1 commit intomainfrom
replayx/incident-checkout-race-001-mo656en0
Open

fix(checkout-api): resolve checkout-race-condition#19
Spkap wants to merge 1 commit intomainfrom
replayx/incident-checkout-race-001-mo656en0

Conversation

@Spkap
Copy link
Copy Markdown
Collaborator

@Spkap Spkap commented Apr 19, 2026

Summary

Resolve checkout-race-condition for checkout-api with a validated ReplayX patch candidate.

Changed Files

  • demo_app/src/inventory/reserve-stock.ts
  • demo_app/src/checkout/submit-order.ts

Validation

  • Concurrent checkout repro: exit 0
  • Sequential checkout sanity: exit 0

Rollback

Revert the live inventory guard and concurrent checkout settlement handling.

Copilot AI review requested due to automatic review settings April 19, 2026 19:11
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses the checkout-race-condition incident in the demo app’s checkout flow by preventing concurrent reservations from overselling inventory and by making the concurrent repro scenario tolerate expected “out of stock” outcomes.

Changes:

  • Add a post-delay, pre-decrement availability guard in reserveStock to prevent inventory from going negative under concurrent checkout attempts.
  • Return reservation metadata (token + snapshotVersion) from the committed inventory record rather than a potentially stale snapshot.
  • Update the concurrent checkout repro to use Promise.allSettled, treating OutOfStock as an expected rejection while still surfacing unexpected failures.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
demo_app/src/inventory/reserve-stock.ts Adds a second availability check after the async delay and returns commit-time snapshotVersion/token to avoid stale results.
demo_app/src/checkout/submit-order.ts Switches concurrent runner to allSettled and filters expected OutOfStock rejections so the repro can succeed without masking hard failures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +23 to +25
if (record.available < quantity) {
throw new Error(`OutOfStock: ${sku}`);
}
Comment on lines +19 to +23
const hardFailure = settled.find(
(result) =>
result.status === "rejected" &&
!(result.reason instanceof Error && result.reason.message.startsWith("OutOfStock:"))
);
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.

2 participants