Conversation
There was a problem hiding this comment.
Pull request overview
Resolves the demo app’s checkout-race-condition by preventing overselling during stock reservation and treating expected OutOfStock failures as non-fatal during concurrent checkout repro runs.
Changes:
- Add a post-delay inventory availability guard in
reserveStockto prevent committing negative inventory under concurrent requests. - Adjust reservation token/version to reflect the committed inventory record version.
- Update concurrent checkout scenario runner to use
Promise.allSettled, ignoreOutOfStockrejections, and only fail on unexpected 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 a post-delay availability check and aligns returned token/version with committed record state. |
| demo_app/src/checkout/submit-order.ts | Switches concurrent mode to allSettled, filters expected OutOfStock failures, and returns only successful results. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Intentional bug: this delay makes the pre-check stale under concurrent checkout attempts. | ||
| await delay(25); | ||
|
|
There was a problem hiding this comment.
The comment above this delay says the pre-check becomes stale under concurrent checkouts, but the new post-delay record.available guard makes this no longer an intentional bug. Please update/remove the comment so it accurately describes the current behavior (e.g., that we re-check after the delay to avoid overselling).
| (result) => | ||
| result.status === "rejected" && | ||
| !(result.reason instanceof Error && result.reason.message.startsWith("OutOfStock:")) | ||
| ); |
There was a problem hiding this comment.
This logic treats "OutOfStock" as a non-fatal rejection by matching on Error.message.startsWith("OutOfStock:"), which is brittle and can easily break if the message changes or the error is thrown from a different realm/type. Consider using a dedicated OutOfStockError class (or an error.code/name field) exported from the inventory layer and checking that instead of parsing the message string.
Summary
Resolve
checkout-race-conditionforcheckout-apiwith a validated ReplayX patch candidate.Changed Files
Validation
Rollback
Revert the live inventory guard and concurrent checkout settlement handling.