Requirements checklist
Run the conversation from the race — everything else follows:
□ the race two users, one seat: first tap wins, at tap time □ holds + TTL picking = exclusive claim, 5 min; expiry frees seats □ payment position external call AFTER the hold; success/fail/timeout □ failure semantics fail -> release hold; timeout -> TTL handles it □ retry-safe confirm duplicate success callbacks: same booking, no error □ seat map anchor per SHOW, not per screen (layout vs availability) □ scope pricing/discounts/food out; single process, in-memory
The core model
Show owns Map seat -> AVAILABLE | HELD | BOOKED (the ONE truth)
screen keeps only the immutable layout
Hold id + seats + owner + expiresAt; all-or-nothing unit
lazy expiry: checked at the top of every mutating call
placeHold one synchronized check-then-claim — the race is decided
here and nowhere else; ANY seat taken -> claim nothing
confirm(holdId) idempotent (booking keyed by hold id); expired -> clean
fail; only live unconfirmed holds book
Lifecycle AVAILABLE -> HELD -> BOOKED; expiry/release -> AVAILABLE
Timeout NO code path — the TTL already bounds every hold
Principles, at their decisions
- Single source of truth: seat state has one owner (the show) and one writer path; the race has exactly one battleground.
- Cohesion: the hold object carries claim, owner, and deadline together — release, expire, confirm are one operation each.
- Idempotency: confirm keyed by hold id — same input, same booking, no second effect.
- Separation of concerns: immutable layout (and later, pricing) apart from hot availability.
Complexity facts
placeHold O(k) for k wanted seats + O(holds) lazy-expiry sweep
confirm/release O(k); all under the show's lock — contention is per show
memory O(seats + live holds) per show; expired holds reclaimed
lazily (correctness) + optional sweep (hygiene)
What earns points, per report dimension
- Requirements & interface — you opened with the F7 race, pinned the TTL, asked about duplicate callbacks, and caught the per-show seat-map anchor.
- Core design & invariants — one writer for seat state, all-or-nothing holds, booking only from a confirmed live hold, all stated unprompted.
- Extension probe — the round will move the requirements; land the change on a seam (layout side, a new guarded transition, the one claim path) and say what survives.
- Complexity honesty — lock scope named (per show), lazy expiry's cost on the mutating path acknowledged.
- Communication — the timeout row ("no code path — the TTL handles it") and the stale-search caveat said out loud.
Ready? Sit the live mock → — the interviewer will run a twist this chapter deliberately hasn't shown you.