events: capacity-safe transactional booking on persist + 24 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 36s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 36s
booking.sx: per-occurrence append-only stream, roster = replay. Booking decided against an observed (roster, last-seq) snapshot, committed via persist/append-expect — atomic check+append, no overbooking, no lock. Explicit last-seat race test: two bookers, one booked, one conflict, roster capped. Idempotent per actor. 97/97 green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,7 @@ capacity rules, transactional booking, and a flow-driven notification dispatcher
|
||||
|
||||
## Status (rolling)
|
||||
|
||||
`bash lib/events/conformance.sh` → **73/73** (Phase 1 complete: calendar + availability + api)
|
||||
`bash lib/events/conformance.sh` → **97/97** (Phase 1 complete + Phase 2 capacity-safe booking)
|
||||
|
||||
## Ground rules
|
||||
|
||||
@@ -62,9 +62,11 @@ lib/events/api.sx ── (events/schedule) (events/book) (events/agenda) ──
|
||||
- [x] tests + scoreboard + conformance.sh (73/73)
|
||||
|
||||
## Phase 2 — Ticketing + booking
|
||||
- [ ] capacity rules; transactional booking → `persist` (no overbooking)
|
||||
- [x] capacity rules; transactional booking → `persist` (no overbooking)
|
||||
- [ ] wire `booking.sx` into `api.sx` (persist-backed `ev/book`)
|
||||
- [ ] cancellation (tombstone events) + seat release
|
||||
- [ ] paid tickets compose with `commerce` order flow
|
||||
- [ ] tests: capacity edge, double-book guard, conflict detection
|
||||
- [x] tests: capacity edge, double-book guard, conflict detection
|
||||
|
||||
## Phase 3 — Notification delivery (flow)
|
||||
- [ ] `notify.sx` — reminder/digest flows over injected transport
|
||||
@@ -79,6 +81,16 @@ lib/events/api.sx ── (events/schedule) (events/book) (events/agenda) ──
|
||||
|
||||
## Progress log
|
||||
|
||||
- 2026-06-07 — **Phase 2 start: capacity-safe booking.** `booking.sx`: one
|
||||
append-only persist stream per occurrence; roster = stream replayed. Booking
|
||||
decisions made against an OBSERVED (roster, last-seq) snapshot, committed via
|
||||
`persist/append-expect` — append only if last-seq unchanged, else a conflict
|
||||
value the booker retries. This makes capacity-check + append atomic at the
|
||||
persist boundary: no overbooking, no lock. `ev/book!` (retrying),
|
||||
`ev/book-with-observed`, `ev/roster`, `ev/seats-left`. Idempotent per actor
|
||||
(:already). Explicit last-seat race test: two bookers on the same snapshot →
|
||||
one :booked, one :conflict, roster never exceeds capacity; loser retry →
|
||||
:full (or next seat when room remains). 24 tests, 97/97 green.
|
||||
- 2026-06-07 — **Phase 1 complete.** `api.sx`: immutable `store`
|
||||
({:events :bookings}) facade over calendar + availability. `ev/schedule`,
|
||||
`ev/book`, `ev/agenda`, `ev/agenda-for`, `ev/free?`, `ev/next-free`,
|
||||
|
||||
Reference in New Issue
Block a user