Idempotency — Two Clicks, One Charge
Two customers reserved the last item
Goal
You tie stock deduction, the reservation id, and cancellation together atomically and prevent overselling.
Why it matters
One item of stock was left, but two requests looked it up at the same time and both succeeded in reserving. Afterward, when the same cancel message arrived twice, the stock became larger than the original. Deduplication of a reservation and deduplication of a cancellation are different state transitions, and the check of the remaining quantity must also be in the same transaction as the deduction.
Steps
- In
/root/work/idem-stock-reservation-lab/service.py, quantity(value) returns only a positive int (not bool), and raises ValueError otherwise.
Prepare it once at the beginning. It does not overwrite an existing file.
mkdir -p /root/work/idem-stock-reservation-lab
test -e /root/work/idem-stock-reservation-lab/service.py || cp /opt/fixtures/ten_labs/idem-stock-reservation-lab/service.py /root/work/idem-stock-reservation-lab/service.py
cd /root/work/idem-stock-reservation-lab
-
In
/root/work/idem-stock-reservation-lab/service.py, init_db(path) idempotently creates stock(sku TEXT PRIMARY KEY,available INTEGER NOT NULL) and reservations(id TEXT PRIMARY KEY,sku TEXT NOT NULL,qty INTEGER NOT NULL,cancelled INTEGER NOT NULL DEFAULT 0). -
In
/root/work/idem-stock-reservation-lab/service.py, add_stock(path,sku,amount) checks for an int of 0 or more (not bool) and INSERTs only a new product. A duplicate product is an IntegrityError. -
In
/root/work/idem-stock-reservation-lab/service.py, available(path,sku) returns the stored quantity and raises KeyError if the product does not exist. -
In
/root/work/idem-stock-reservation-lab/service.py, reserve(path,rid,sku,qty,fault=lambda:None) validates the quantity. An existing reservation id gives False if it has the same product and quantity, and ValueError if it differs. A new reservation checks that the product exists and the stock, and returns True after deduct → fault → insert reservation. A shortage or a nonexistent product is a ValueError. -
In
/root/work/idem-stock-reservation-lab/service.py, cancel(path,rid) returns False for a reservation that does not exist or is already cancelled. For an active reservation, it performs cancelled=1 and the stock return in the same transaction and returns True. -
In
/root/work/idem-stock-reservation-lab/service.py, reservation(path,rid) returns a (sku,qty,cancelled) tuple or None. -
In
/root/work/idem-stock-reservation-lab/service.py, compete(path,sku) runs reserve in two threads with different ids first and second and a quantity of 1. It returns the list of results in input order, with only ValueError turned into False.
Notes
- Do it in the existing lab-dev environment, without the internet or package installation.
- Each step runs within a 45-second grading budget. Do not add real sleep or network calls.
- Grading freshly imports the submitted module and checks it with independent inputs and a temporary DB. Implement the contract instead of returning expected values as constants.
- FastAPI official documentation · pytest official documentation · Python sqlite3
- Limitation: this is not a lab that ties payment approval and stock reservation into one distributed transaction. Reservation expiry and compensation for payment failure are separate flows. With a small SQLite DB, you learn the principle of not trusting the stock number at lookup time and checking it inside the transaction that writes.
Pin the quantity down as an integer contract
In /root/work/idem-stock-reservation-lab/service.py, quantity(value) returns only a positive int (not bool), and raises ValueError otherwise.
Prepare it once at the beginning. It does not overwrite an existing file.
mkdir -p /root/work/idem-stock-reservation-lab
test -e /root/work/idem-stock-reservation-lab/service.py || cp /opt/fixtures/ten_labs/idem-stock-reservation-lab/service.py /root/work/idem-stock-reservation-lab/service.py
cd /root/work/idem-stock-reservation-lab
Keep a negative reservation from increasing stock.
After saving, check with bash /opt/lab/checks/idem-stock-reservation-lab/01-contract.sh.
Store stock and reservations separately
In /root/work/idem-stock-reservation-lab/service.py, init_db(path) idempotently creates stock(sku TEXT PRIMARY KEY,available INTEGER NOT NULL) and reservations(id TEXT PRIMARY KEY,sku TEXT NOT NULL,qty INTEGER NOT NULL,cancelled INTEGER NOT NULL DEFAULT 0).
A cancelled reservation must also remain so that you can tell the same cancellation from a re-reservation.
After saving, check with bash /opt/lab/checks/idem-stock-reservation-lab/02-contract.sh.
Distinguish product initialization from a stock change
In /root/work/idem-stock-reservation-lab/service.py, add_stock(path,sku,amount) checks for an int of 0 or more (not bool) and INSERTs only a new product. A duplicate product is an IntegrityError.
Keep the same initialization command from overwriting stock that is in use.
After saving, check with bash /opt/lab/checks/idem-stock-reservation-lab/03-contract.sh.
Look up the remaining quantity
In /root/work/idem-stock-reservation-lab/service.py, available(path,sku) returns the stored quantity and raises KeyError if the product does not exist.
Distinguish a nonexistent product from sold out so that a wrong product id is not hidden.
After saving, check with bash /opt/lab/checks/idem-stock-reservation-lab/04-contract.sh.
Tie the reservation and the stock deduction together
In /root/work/idem-stock-reservation-lab/service.py, reserve(path,rid,sku,qty,fault=lambda:None) validates the quantity. An existing reservation id gives False if it has the same product and quantity, and ValueError if it differs. A new reservation checks that the product exists and the stock, and returns True after deduct → fault → insert reservation. A shortage or a nonexistent product is a ValueError.
Put the check and the deduction in the same transaction and roll back everything on a failure.
After saving, check with bash /opt/lab/checks/idem-stock-reservation-lab/05-contract.sh.
Reflect a cancellation only once too
In /root/work/idem-stock-reservation-lab/service.py, cancel(path,rid) returns False for a reservation that does not exist or is already cancelled. For an active reservation, it performs cancelled=1 and the stock return in the same transaction and returns True.
Stock must not keep increasing because of a resend of the cancel message.
After saving, check with bash /opt/lab/checks/idem-stock-reservation-lab/06-contract.sh.
Check the reservation state
In /root/work/idem-stock-reservation-lab/service.py, reservation(path,rid) returns a (sku,qty,cancelled) tuple or None.
Read not just the return value but whether the cancelled state remained in the DB.
After saving, check with bash /opt/lab/checks/idem-stock-reservation-lab/07-contract.sh.
Reproduce the race for the last stock
In /root/work/idem-stock-reservation-lab/service.py, compete(path,sku) runs reserve in two threads with different ids first and second and a quantity of 1. It returns the list of results in input order, with only ValueError turned into False.
You have to compare two situations, stock 1 and stock 2, to filter out an implementation that unconditionally lets only one succeed.
After saving, check with bash /opt/lab/checks/idem-stock-reservation-lab/08-contract.sh.