Process 06.2 — Reveal ceremony broadcast
Process 06.2 — Reveal ceremony broadcast
Section titled “Process 06.2 — Reveal ceremony broadcast”Sequence for the 00:00 UTC reveal ceremony, when the winning ad for date D activates and the public landing page plays the cinematic.
Clarification vs master design. Master §1 specifies “Every day at 00:00 UTC a sealed-bid auction closes for an ad slot 24 hours later” (close) and §5 acceptance gate item 8: “at 00:00 UTC T, the winning creative is the Spotlight” (activation). The cinematic reveal animation is therefore triggered by the activation message at 00:00 UTC of day T — not by the close at 00:00 UTC of day T−1. The same 00:00 UTC wall-clock instant fires both the previous auction’s close (saga starts) and the previous day’s saga-activation (today’s ad goes live). This process diagram covers the activation reveal branch.
Why HubDO does the lobby fan-out, not each AuctionDO.
- Lobby viewers are subscribed to
HubDO("lobby"), not to any specificAuctionDO. They learn “today’s winner” from a single message in a single DO. This bounds the broadcast to one DO’s ~1 k msg/s envelope and lets us chunk-pace within it. - AuctionDO(D)‘s remaining subscribers receive the terminal
auction_closedclose-out from the auction close path, not from the reveal ceremony. Browser UI handling for combining reveal and terminal auction state is tracked in #230.
Thundering-herd mitigations applied here.
- Chunked fan-out — 256 sockets per loop iteration,
await scheduler.wait(0)between chunks to yield to the runtime. Prevents a single synchronous burst from starving other DO work. - CF cache purge before broadcast — the message tells the client “the new ad is live”; if a client fetches
/in response, the edge already serves the new HTML, no origin stampede. - OG image pre-rendered during saga’s
ACTIVATEstep, well before this fan-out — no live image-render under load. - Client animation is local — the WS message carries
winning_ad_id; the creative HTML for/day/Dis already in CF cache. No back-and-forth. - Bypass-batch but still uses the envelope+seq machinery — clients in
replaystate during reconnect after the storm still seespotlight_revealedin order.
Failure modes & responses.
- HubDO unreachable mid-fan-out. Some lobby sockets miss the message. They reconnect (visibilitychange or backoff), send
last_seq, get areplayincludingspotlight_revealedfrom the HubDO ring buffer. Worst-case 5–8s late cinematic — acceptable; the ad itself is live regardless. - Activation but no spotlight_revealed (Hub broadcast fails entirely). Public site shows the new ad on next page load (cache-purged); cinematic is best-effort, the data layer is authoritative. No saga retry needed for the WS step.
- Saga retries
ACTIVATE.announceRevealis idempotent per(date, winning_ad_id); HubDO dedupes on that key before incrementingseq.
Files referenced.
apps/cron/src/index.ts— 00:00 UTC scheduled trigger.packages/saga/src/campaign-saga.ts—ACTIVATEstep callsenv.WS_HUB.fetch("/internal/announce-reveal", ...)via service binding.apps/ws/src/index.ts—POST /internal/announce-revealroute, gated by a shared secret/service-binding header.apps/ws/src/websocket-hub.ts—announceReveal({date, winning_ad_id})parse, idempotency, ring append, and chunked fan-out.apps/api/src/auction-do.ts— terminal flush +auction_closedenvelope for the auction close path.