Fans one replica's broadcast out to every other connected replica.
This class holds no state. Not as a simplification — as a correctness
requirement. Sockets are accepted with state.acceptWebSocket, the
hibernation API, which lets the Workers runtime evict the Durable Object from
memory while its connections stay open and re-run the constructor when
the next message arrives. A membership Set held in a field would therefore
empty itself on the first hibernation, and every test that never hibernates
would still pass. state.getWebSockets() survives hibernation and is the
only source of truth used here.
The payload is re-broadcast verbatim, never parsed. That costs no CPU per
fan-out, makes it impossible for this object to corrupt a frame, and — since
a Durable Object class is deployed by the application rather than by this
package — means a future widening of RealtimeFrame needs no redeploy of the
object to carry the new field.
The application owns the class; this owns the behavior:
Example 1
Example 1
import { DurableObject } from 'cloudflare:workers'; import { RealtimeBackplaneObjectCore } from '@setu-ts/cloudflare-plugin'; export class RealtimeBackplaneObject extends DurableObject { #core = new RealtimeBackplaneObjectCore(this.ctx); override fetch(request: Request): Promise<Response> { return this.#core.fetch(request); } webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void { this.#core.webSocketMessage(ws, message); } webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean): void { this.#core.webSocketClose(ws, code, reason, wasClean); } }
RealtimeBackplaneObjectCore(state: IDurableObjectState,options?: RealtimeBackplaneObjectCoreOptions)
state: IDurableObjectState
The Durable Object's ctx
options: RealtimeBackplaneObjectCoreOptions
Optional seams; the defaults are the deployment path
webSocketClose(): void
Handles a replica disconnecting.
Nothing is tracked, so nothing needs removing — the runtime drops the
socket from getWebSockets() on its own. The handler exists so the
application's class can forward it without a branch, and so the close is
acknowledged rather than left to the runtime's default.
webSocketError(socket: IDurableObjectWebSocket): void
Handles a socket error.
The runtime closes the socket itself, so this only prevents an unhandled rejection inside the application's class.
webSocketMessage(sender: IDurableObjectWebSocket,message: string | ArrayBuffer): void
Re-broadcasts one replica's message to every other connected replica.