Import these from @grafloria/engine.
Classes
BroadcastChannelTransport
tsclass BroadcastChannelTransport implements SyncTransport
Methods
constructor(private readonly options: BroadcastChannelTransportOptions)get status(): TransportStatusstatic isSupported(): boolean(static) — True when this environment can actually do cross-tab sync.connect(): void— Open (or re-open) the channel. Idempotent.send(message: SyncMessage): void— Broadcast to the other peers. A no-op — NOT an error — while disconnected.onMessage(handler: (m: SyncMessage) => void): Unsubscribe— Inbound messages from other peers. Never our own.onStatus(handler: (s: TransportStatus) => void): Unsubscribe— Connection transitions. THE hook the whole reconnect story hangs on: the adapter subscribes here and fires an anti-entropy round the moment it hears 'connected' again. A transport that never reports its status can never be caught up.disconnect(): void— Simulates (and, onpagehide, effects) a drop. Re-connect()to come back.close(): void— Tear down for good.
CausalBuffer
Holds ops whose entity has not been added yet, and releases them the instant it is.
Sits BETWEEN the transport and the Replica. Nothing it holds has touched the log, the clock or the LWW registry — which is the whole point: an op the replica has never seen is an op that can still be applied later.
tsclass CausalBuffer
Properties
| Name | Type | Default | Description |
|---|---|---|---|
overflowed | 0 | Ops force-released because the buffer was full. Should be 0. Watch it. |
Methods
constructor( private readonly diagram: DiagramModel, options: CausalBufferOptions = {} )get pendingCount(): numbernoteLocal(op: Op): void— WE created an entity. Record it — the transport will never tell us about it.admit(incoming: readonly Op[]): CausalSplit— Split an arriving batch into what can be applied now and what must wait — and fold in anything that was already waiting and has just become releasable.pending(): Op[]— Everything we are still holding — for a status panel, and for the tests.
MemoryHub
A shared bus. One hub = one document = one "room".
tsclass MemoryHub
Properties
| Name | Type | Default | Description |
|---|---|---|---|
traffic | Array<{ from: ActorId; message: SyncMessage }> | [] | Every message that crossed the bus — the wire tap the tests assert against. |
Methods
connect(actor: ActorId): MemoryTransportdeliver(from: MemoryTransport, message: SyncMessage): void— Deliver to everyone EXCEPT the sender. A peer never hears its own echo.detach(port: MemoryTransport): voidget peerCount(): number
MemoryTransport
tsclass MemoryTransport implements SyncTransport
Methods
constructor( private readonly hub: MemoryHub, readonly actor: ActorId )get status(): TransportStatussend(message: SyncMessage): void— Broadcast to the other peers. A no-op — NOT an error — while disconnected.accept(message: SyncMessage): void— Inbound. Ignored while disconnected — a dropped peer hears nothing, by definition.onMessage(handler: Handler): Unsubscribe— Inbound messages from other peers. Never our own.onStatus(handler: (s: TransportStatus) => void): Unsubscribe— Connection transitions. THE hook the whole reconnect story hangs on: the adapter subscribes here and fires an anti-entropy round the moment it hears 'connected' again. A transport that never reports its status can never be caught up.connect(): void— Open (or re-open) the channel. Idempotent.disconnect(): void— Close the channel but stay re-openable — this is what a "drop" is.close(): void— Tear down for good.
OpBatcher
Accumulates local ops and flushes them as one coalesced, correctly-ordered batch.
tsclass OpBatcher
Properties
| Name | Type | Default | Description |
|---|---|---|---|
queued | 0 | Ops that went in. | |
sent | 0 | Ops that went out. queued - sent is what coalescing saved. | |
batches | 0 | Flushes performed. |
Methods
constructor(private readonly options: OpBatcherOptions)get size(): numberpush(op: Op): voidflush(): void— Send whatever is queued, right now. Idempotent, and a no-op when empty.discard(): void— Drop the queue WITHOUT sending.dispose(): void
UnreliableHub
Also has every member of MemoryHub, listed on its own entry.
A MemoryHub with the network's malice put back.
Same API, same adapters, same protocol — the ONLY difference is that this one behaves like the internet. If the sync layer is correct, nothing above it needs to change; if it is not, this is where you find out.
tsclass UnreliableHub extends MemoryHub
Properties
| Name | Type | Default | Description |
|---|---|---|---|
faults | What the network actually did. Asserted on — a fuzz whose faults never fired is a lie. |
Methods
constructor(options: UnreliableOptions = {})override deliver(from: MemoryTransport, message: SyncMessage): void— Deliver to everyone EXCEPT the sender. A peer never hears its own echo.step(fraction = 0.5): number— Release some of the in-flight queue, in a RANDOM order.heal(): void— Stop breaking things. The network has recovered; from here on it is a plain, honest bus. Anything still lost was lost DURING the storm, and anti-entropy — not the transport — is what has to find it.settle(): void— Deliver everything still in flight.get inFlightCount(): numberoverride connect(actor: ActorId): MemoryTransport
VersionVector
A peer's exact position in the shared history, per actor.
Fed ONLY with ops the log genuinely accepted (Replica.receive() returns exactly
those). Feed it a duplicate and count over-counts, which fakes a hole and triggers a
pointless repair — wasteful, not wrong, but the discipline is worth keeping.
tsclass VersionVector
Methods
observe(op: Op): void— Record ONE op we now hold. Must be genuinely new — see the class doc.observeAll(ops: Iterable<Op>): voidfrontier(actor: ActorId): ActorFrontierget actorCount(): numbertoJSON(): VersionVectorJSONstatic fromOps(ops: Iterable<Op>): VersionVector(static) — Rebuild from a log — used on resume-from-disk, and by the tests as an oracle.
WebSocketTransport
tsclass WebSocketTransport implements SyncTransport
Properties
| Name | Type | Default | Description |
|---|---|---|---|
attempts | 0 | Reconnect attempts made. Asserted on by the backoff test. |
Methods
constructor(private readonly options: WebSocketTransportOptions)get status(): TransportStatusconnect(): void— Open (or re-open) the channel. Idempotent.send(message: SyncMessage): void— Broadcast to the other peers. A no-op — NOT an error — while disconnected.onMessage(handler: (m: SyncMessage) => void): Unsubscribe— Inbound messages from other peers. Never our own.onStatus(handler: (s: TransportStatus) => void): Unsubscribe— Connection transitions. THE hook the whole reconnect story hangs on: the adapter subscribes here and fires an anti-entropy round the moment it hears 'connected' again. A transport that never reports its status can never be caught up.disconnect(): void— Close the channel but stay re-openable — this is what a "drop" is.close(): void— Tear down for good.
Was this page helpful?