Skip to content

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

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

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

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 18:48
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 demo app’s checkout-race-condition by ensuring inventory reservations re-validate against live state at commit time, and by adjusting the concurrent checkout repro flow to tolerate expected out-of-stock outcomes.

Changes:

  • Add a post-delay availability guard in reserveStock to prevent overselling under concurrent requests.
  • Return committed snapshotVersion/reservationToken values from the live inventory record (instead of the stale snapshot).
  • Update the concurrent race scenario to use Promise.allSettled and only fail on non-out-of-stock errors.

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 commit-time stock validation and returns committed version/token values to eliminate stale snapshot usage.
demo_app/src/checkout/submit-order.ts Treats out-of-stock as an expected concurrent outcome by settling requests and filtering soft failures.

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

Comment on lines 19 to +23
await delay(25);

const record = getInventoryRecord(sku);

if (record.available < quantity) {
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

The comment above this block says the delay is an “Intentional bug”, but with the new post-delay record.available check this function is no longer relying on a stale pre-check. Please update/remove that comment so it doesn’t mislead future readers about the current behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +23
const hardFailure = settled.find(
(result) =>
result.status === "rejected" &&
!(result.reason instanceof Error && result.reason.message.startsWith("OutOfStock:"))
);
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

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

runCheckoutRaceScenario treats out-of-stock as a soft failure by parsing error.message (startsWith("OutOfStock:")). This is brittle and couples callers to a specific error string; consider using a dedicated error type (e.g., class OutOfStockError) or a structured discriminator (e.g., error.name/code) exported from the inventory layer so the check remains stable if the message changes.

Copilot uses AI. Check for mistakes.
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