import './utils/disposable'; import { MessageBus } from './MessageBus'; import type { FrameKind, FramePayload, Logger } from './types'; /** * At-least-once outbox for follower-originated dispatches. * * When a follower calls `send()`, the frame is published over the bus for the * leader to write. If the leader dies between receiving the dispatch and * writing it to the socket, the frame would be lost — so each `event` dispatch * is buffered locally with a unique id. The leader broadcasts `ws:dispatch- * flushed` once it processes the dispatch and the originator drops the entry. * On leader change, the new leader gathers still-pending entries from every * surviving tab and replays them over the fresh socket. * * Extracted from SharedWebSocket so the buffer + gather/replay protocol is one * cohesive unit. (Only `event` kinds are buffered — channel/topic/auth frames * are re-established separately by resubscribe-on-connect.) */ export declare class Outbox implements Disposable { private readonly bus; private readonly maxSize; /** Writes a frame to the live socket — supplied by the owner (FramePipeline). */ private readonly transmit; private readonly log; private readonly pending; private cleanups; constructor(bus: MessageBus, maxSize: number, /** Writes a frame to the live socket — supplied by the owner (FramePipeline). */ transmit: (kind: FrameKind, payload: FramePayload) => void, log: Logger); get size(): number; /** * Route a follower dispatch to the leader. Buffers `event` kinds locally for * replay across handover, then publishes for the leader's socket. Channel / * topic / auth frames are not buffered — they're re-sent by * resubscribe-on-connect, so buffering them too would double-emit. */ route(kind: FrameKind, payload: FramePayload): void; private enqueue; /** * New-leader replay: gather still-pending dispatches from all tabs (including * this one), transmit each over the fresh socket, then signal every * originator to drop its entry. `isValid` lets the caller bail if the socket * was replaced again while we were gathering (avoids replaying onto a socket * that's already gone, which would drop entries that never actually sent). */ replay(isValid?: () => boolean): Promise; /** * Cross-tab pending-dispatch gather. Broadcasts a one-shot request, collects * for a short window, dedups by id (so multiple tabs holding the same id * don't double-replay). */ private gather; [Symbol.dispose](): void; }