Hoppa till huvudinnehåll
Petanque Life

Wait-List & Dynamic Re-Allocation (PL-T197)

F22.15 16 features

I korthet

A FIFO wait-list with auto-promotion when slots free up — keyed per (resource_type, time_range). SMS-alert with configurable response deadline snapshotted per entry, race-safe token-based accept that 409s losers and auto-promotes the next candidate, position recompute on every queue change, supersede-and-requeue on maintenance, hourly metrics rollup for materialized wait-time estimates, customer-cancel-mid-promotion handling, and a tenant killswitch via WaitListPolicy.enabled.

Så fungerar det

When a booking attempt 409s on conflict, the customer can opt into the wait-list — a WaitListEntry is written into a FIFO bucket keyed on (resource_type, time_range), with an integer position field. When a booking in that bucket is cancelled or maintenance closes a slot, WaitListService.promote_for_freed_slot picks the head of the queue and creates a WaitListPromotion document with status pending. A waitlist_promoted event fires through the notifications hub — the candidate gets an SMS with a tokenized accept/decline link.

The promotion_response_window_minutes from the venue profile is snapshotted onto the entry at promotion time so policy changes don't disturb in-flight promotions. POST /chain/waitlist/promotions/{id}/accept (token-based, no login required) is race-safe: if two candidates somehow accept the same slot, the loser gets 409 slot_unavailable and the system auto-promotes the next. POST /decline records an optional reason.

The waitlist-expiration-tick cron runs every minute, expiring unaccepted promotions and promoting the next candidate. Position is recomputed FIFO on every create / cancel / promote so the queue never has gaps. handle_resource_unavailable supersedes affected promotions back to WAITING when maintenance is added retroactively. Customer cancel mid-promotion flips status to SUPERSEDED and offers the slot to the next candidate.

An hourly waitlist-position-metrics rollup materializes estimated_wait_minutes per bucket so customers see realistic ETAs before committing. SSE broadcasts on chain.waitlist.{tenant}.{location} and the per-entry channel chain.waitlist.entry.{id} keep the operator console and the customer's confirmation page live. Default sv/en SMS+email templates are seeded on first profile-create.

WaitListPolicy.enabled = false is a tenant killswitch that disables the entire feature without code changes.

Centrala funktioner

  • FIFO queue per (resource_type, time_range) with auto-promote on cancellation
  • WaitListPromotion status machine (pending → accepted/declined/expired/superseded) with token-based guest access
  • Race-safe accept — concurrent winners get 409 + auto-promote next
  • Position recompute on every create/cancel/promote + per-entry response-window snapshot
  • Supersede + re-queue on maintenance + customer-cancel mid-promotion
  • Hourly metrics rollup → materialized estimated_wait_minutes
  • SSE broadcasts + tenant killswitch via WaitListPolicy.enabled

I praktiken

Saturday at 18:30 a customer tries to book Lane 4 for 19:30. The slot is full — 409 with a wait-list option. They opt in; a WaitListEntry is written at position 3 in the (court, 19:00-20:30) bucket and the page shows estimated wait 45 min based on the materialized rollup.

At 19:10 another booking cancels. The promotion engine picks position 1 (someone ahead of them), fires SMS "You're in! Reply YES within 10 minutes".

Five minutes pass with no reply; the cron expires that promotion, picks position 2 — same story. At 19:20 it reaches our customer; SMS arrives, they tap the accept link, the booking is created and they get an instant confirmation. Their page (still open in the background) updates via SSE — "You're in, head over" — and they walk in by 19:35.

Features i detta subsystem

16
ID Status Funktioner
F22.15.01 Levererad FIFO queue per resource type + time range (WaitListEntry.position)
F22.15.02 Levererad Auto-promote on cancellation (WaitListService.promote_for_freed_slot)
F22.15.03 Levererad SMS-alert with configurable response deadline (waitlist_promoted event)
F22.15.04 Levererad Cron job for expired deadlines (waitlist-expiration-tick, every minute)
F22.15.05 Levererad WaitListPromotion-dokument med statusmaskin pending → accepted/declined/expired/superseded
F22.15.06 Levererad POST /chain/waitlist/promotions/{id}/accept med token-baserad guest-access
F22.15.07 Levererad POST /chain/waitlist/promotions/{id}/decline med valfritt skäl
F22.15.08 Levererad Position-recompute vid create/cancel/promote (FIFO inom bucket)
F22.15.09 Levererad Snapshot av promotion_response_window_minutes per entry
F22.15.10 Levererad handle_resource_unavailable — supersede + retur till WAITING vid maintenance
F22.15.11 Levererad Race-säkert accept (concurrent → slot_unavailable 409 + auto-promote nästa)
F22.15.12 Levererad Hourly waitlist-position-metrics-rollup för materialiserad estimated_wait_minutes
F22.15.13 Levererad SSE-broadcast på chain.waitlist.{tenant}.{location} + chain.waitlist.entry.{id}
F22.15.14 Levererad Default-templates (sv/en × SMS/email) seedas vid första profile-create
F22.15.15 Levererad Tenant-killswitch via WaitListPolicy.enabled=False
F22.15.16 Levererad Customer cancel mid-promotion → SUPERSEDED + nästa kandidat erbjuds