The events peer's ticket purchase now goes through lib/events' ATOMIC booking instead of a read-check-write race — real domain logic dropping in under the same clickable cinema, exactly as the seam promised. - MODULES (serve.sh + conformance.sh): load lib/persist/concurrency.sx (append-expect/conflict?) + lib/events/booking.sx. host/blog-store (persist/open) is stream-capable, same backend lib/events tests use. - host/blog-buy-ticket: replaced '(< (len sold) capacity)' with (ev/book! host/blog-store <showing> <capacity> <actor>); proceed only on :status :booked. occ-key = showing slug, capacity = host/blog--showing-capacity, actor = email + current roster len (unique per seat, collapses double-clicks, allows a person to hold several seats). persist append-expect retries on conflict — no oversell even under concurrent buys. - Per-offering cap + the sold-edge display are unchanged (render-safe); ev/book! is the authoritative gate in the handler. VERIFIED LIVE on events.rose-ash.com: cap-2 showing → 3 buys, exactly 2 booked (3rd refused); cap-1 showing → 10 CONCURRENT buys → exactly 1 sold, SOLD OUT. Sandbox: ev/book! returns booked/booked/full/already for a cap-2 occ. blog 218/218 (with the two new modules loaded). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
18 KiB
Executable File
18 KiB
Executable File