Skip to content
D
Documentation

Sync — classes

reference
3 min readUpdated

Classes

Import these from @grafloria/engine.

Classes

BroadcastChannelTransport

ts
class BroadcastChannelTransport implements SyncTransport

Methods

  • constructor(private readonly options: BroadcastChannelTransportOptions)
  • get status(): TransportStatus
  • static 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, on pagehide, effects) a drop. Re-connect() to come back.
  • close(): void — Tear down for good.

MemoryHub

A shared bus. One hub = one document = one "room".

ts
class MemoryHub

Properties

NameTypeDefaultDescription
trafficArray<{ from: ActorId; message: SyncMessage }>[]Every message that crossed the bus — the wire tap the tests assert against.

Methods

  • connect(actor: ActorId): MemoryTransport
  • deliver(from: MemoryTransport, message: SyncMessage): void — Deliver to everyone EXCEPT the sender. A peer never hears its own echo.
  • detach(port: MemoryTransport): void
  • get peerCount(): number

MemoryTransport

ts
class MemoryTransport implements SyncTransport

Methods

  • constructor( private readonly hub: MemoryHub, readonly actor: ActorId )
  • get status(): TransportStatus
  • send(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.

ts
class OpBatcher

Properties

NameTypeDefaultDescription
queued0Ops that went in.
sent0Ops that went out. queued - sent is what coalescing saved.
batches0Flushes performed.

Methods

  • constructor(private readonly options: OpBatcherOptions)
  • get size(): number
  • push(op: Op): void
  • flush(): void — Send whatever is queued, right now. Idempotent, and a no-op when empty.
  • discard(): void — Drop the queue WITHOUT sending.

Used on disconnect, and it is safe for exactly one reason: the ops are already in the local log, so the peer will get them from the next anti-entropy round. If they were not, this would be a silent data-loss hatch.

  • dispose(): void

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.

ts
class VersionVector

Methods

  • observe(op: Op): void — Record ONE op we now hold. Must be genuinely new — see the class doc.
  • observeAll(ops: Iterable<Op>): void
  • frontier(actor: ActorId): ActorFrontier
  • get actorCount(): number
  • toJSON(): VersionVectorJSON
  • static fromOps(ops: Iterable<Op>): VersionVector (static) — Rebuild from a log — used on resume-from-disk, and by the tests as an oracle.

WebSocketTransport

ts
class WebSocketTransport implements SyncTransport

Properties

NameTypeDefaultDescription
attempts0Reconnect attempts made. Asserted on by the backoff test.

Methods

  • constructor(private readonly options: WebSocketTransportOptions)
  • get status(): TransportStatus
  • 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 — Close the channel but stay re-openable — this is what a "drop" is.
  • close(): void — Tear down for good.

Was this page helpful?