/** * Install (or replace) the replay-buffer config. Pass `null` to disable * and drop all buffered state. Safe to call multiple times. */ export declare function setReplayBuffer(cfg: ReplayBufferConfig | null): void; /** Read the current config — useful for tests. */ export declare function getReplayBuffer(): Readonly | null; /** * Called by the broadcast wrapper for every outbound message on a * matched channel. Records the message and assigns a monotonic seq. * Returns the seq for the caller to optionally include in the * outbound payload — clients store the latest seq locally and send * it back on reconnect via `replaySince`. */ export declare function recordBroadcast(channel: string, event: string, data: unknown): number | null; /** * Replay every buffered message on `channel` with `seq > sinceSeq`. * Stale entries (older than `ttlMs`) are evicted on the way through * so callers don't see them. Returns the array of messages the * caller should re-send to the reconnecting client. * * @example * ```ts * // Inside the reconnect handler: * const missed = replaySince('orders', lastSeenSeq) * for (const msg of missed) { * socket.send(JSON.stringify({ event: msg.event, data: msg.data, seq: msg.seq })) * } * ``` */ export declare function replaySince(channel: string, sinceSeq: number): BufferedMessage[]; /** * Drop expired entries across every tracked channel. Called by apps * that want eager memory reclaim — the default lazy-on-read path is * adequate for most workloads. */ export declare function pruneExpired(): void; /** * Snapshot the buffer state — debugging only. Don't depend on this * shape in production code; the internals may change. */ export declare function debugSnapshot(): Record; /** * Per-channel message replay buffer (stacksjs/stacks#1877 R-3). * * Background: ts-broadcasting delivers messages at-most-once — a client * that drops between two broadcasts loses everything in flight. For * channels where the app needs every message (chat, presence, order * updates), reconnect-after-network-blip becomes a silent data loss. * * Fix: opt-in per-channel ring buffer that retains the most-recent N * messages with monotonic sequence IDs. On reconnect, the client sends * its last-seen seq; the server replays everything stored after that * point. Apps install via `setReplayBuffer({ channels, maxPerChannel, * ttlMs })`. Buffer is in-process — for cross-instance replay, route * through a shared store (Redis Streams, Postgres LISTEN/NOTIFY, etc.). * * Memory shape: `Map>`. Bounded by * `maxPerChannel` (default 100) so a chatty channel can't OOM the * server. Entries past `ttlMs` are evicted lazily on read — apps that * want eager eviction can call `pruneExpired()` from their own timer. */ export declare interface ReplayBufferConfig { channels?: string[] maxPerChannel?: number ttlMs?: number } export declare interface BufferedMessage { seq: number ts: number event: string data: unknown } declare interface ChannelState { messages: BufferedMessage[] nextSeq: number } declare interface BufferRegistry { channels: string[] maxPerChannel: number ttlMs: number state: Map }