import { type On } from "../events.ts"; import { type WebSocketEventMap, type WebSocketLike, type WebSocketOptions } from "../ws.ts"; import type { Retry } from "./retry.ts"; /** * `ResilientWebSocket` wraps the provided WebSocket client and makes it * resilient to network disruptions and abrupt closures. It implements the * {@link WebSocketLike `WebSocketLike`} interface, so it can be further * wrapped to add behaviors. Every time the underlying connection is abruptly * closed, `ResilientWebSocket` tries to reopen it according to the provided * retry policy: * * When opening connection with `resilient.open()`, the first attempt to connect * is made immediately. If it fails, retry policy is applied with attempt = 1. * If retry policy doesn't allow further attempts, or if the connection is not * opened within {@link ResilientWebSocketOptions.maxTimeoutMs `maxTimeoutMs`}, * both the `resilient.open()` and the `resilient.healthy()` promises are * rejected. Otherwise, another attempt is made, and the attempt counter is * incremented. * * When a previously opened connection closes abruptly, the `reconnect` event * is dispatched. The first attempt to connect is made immediately. If it * fails, retry policy is applied with attempt = 1. If retry policy doesn't * allow further attempts, or if the connection is not opened within * {@link ResilientWebSocketOptions.maxTimeoutMs `maxTimeoutMs`}, * the `resilient.open()` promise is rejected, and the `gaveup` event is * dispatched. Otherwise, another attempt is made, and the attempt counter is * incremented. * * Both the `resilient.open()` and the `resilient.healthy()` promises resolve * with the return value of the `open()` method on the wrapped client, and * reject with an error that has the latest reason for connection to fail as * its `cause`. */ export interface ResilientWebSocket extends WebSocketLike { /** * @see {@link WebSocketClient.on} */ on: On>; /** * Returns a promise resolving when connection is opened. If connection is * currently opened ("healthy"), it resolves immediately. Otherwise, it * resolves as soon as current reconnection attempt succeeds. If the attempt * fails ("gives up"), it rejects with an error that has the latest reason * for connection to fail as its `cause`. * * It's recommended to always await for the connection to be healthy before * sending messages with `resilient.send()` or executing procedures with * `resilient.exec()`: * * ```ts * await resilient.healthy(); * await resilient.send('hello'); * ``` * * This method resolves with the return value of the `open()` method on * the wrapped client. * * If connection is cancelled by calling `ws.close()`, this method rejects * with {@link AbortedError `AbortedError`}. * * If connection gives up, this method rejects with an error that has * the latest reason for connection to fail as its `cause`. */ healthy(): Promise; } export interface ResilientWebSocketOptions { /** * Retry policy to be used when reconnecting. Can be one of built-in * policies (`exponentialBackoff()` or `indefinetely()`) or a custom one. * * @see {@link Retry} */ retry: Retry; /** * Maximum duration in milliseconds that the connection can be disrupted. * After trying to reconnect for `maxTimeoutMs`, `ResilientWebSocket` gives * up further attempts to retry. */ maxTimeoutMs: number; /** * Optional list of codes that are considered normal status codes. No * reconnection attempts are made if the connection closes with one of these * codes, and the `close` event is dispatched as usual. */ allowedCloseCodes?: number[]; } type ResilientWebSocketEventMap = ResilientWebSocketOwnEventMap & WebSocketEventMap; type ResilientWebSocketOwnEventMap = { /** * The `close` event is dispatched when a connection is closed "externally" * with one of the {@link ResilientWebSocketOptions.allowedCloseCodes allowed status codes}. * * @see {@link WebSocketEventMap.close} */ close: (code: number, reason: string) => void; /** * The `reconnect` event is dispatched when the connection is closed abruptly * and before any reconnection attempts are made. * * @param code Status code for the abrupt closure sent by the server * @param reason Reason for the abrupt closure specified by the server */ reconnect: (code: number, reason: string) => void; /** * The `gaveup` event is dispatched when no further reconnection attempts can * be made, either because the retry policy doesn't allow it, or the * {@link ResilientWebSocketOptions.maxTimeoutMs `maxTimeoutMs`} timeout has * been reached. * * @param error The latest reason for connection to fail * @param code Status code for the abrupt closure sent by the server * @param reason Reason for the abrupt closure specified by the server */ gaveup: (error: any, code: number, reason: string) => void; }; /** * Creates a new `WebSocketClient` and wraps it with the * {@link ResilientWebSocket `ResilientWebSocket`} behavior. */ export declare function createResilientWebSocketClient(options: WebSocketOptions & ResilientWebSocketOptions): ResilientWebSocket; /** * Wraps an existing `WebSocketClient` with the * {@link ResilientWebSocket `ResilientWebSocket`} behavior. */ export declare function makeResilient(ws: WebSocketLike, options: ResilientWebSocketOptions): ResilientWebSocket; export {}; //# sourceMappingURL=resilient.d.ts.map