UNPKG

@jellyfish-dev/ts-client-sdk

Version:
99 lines (98 loc) 3.45 kB
import { isAuthError } from "./auth"; const DISABLED_RECONNECT_CONFIG = { maxAttempts: 0, initialDelay: 0, delay: 0, addTracksOnReconnect: false, }; const DEFAULT_RECONNECT_CONFIG = { maxAttempts: 3, initialDelay: 500, delay: 500, addTracksOnReconnect: true, }; export class ReconnectManager { reconnectConfig; connect; client; initialMetadata = undefined; reconnectAttempt = 0; reconnectTimeoutId = null; reconnectFailedNotificationSend = false; ongoingReconnection = false; lastLocalEndpoint = null; constructor(client, connect, config) { this.client = client; this.connect = connect; this.reconnectConfig = createReconnectConfig(config); this.client.on("socketError", () => { this.reconnect(); }); this.client.on("socketClose", (event) => { if (isAuthError(event.reason)) return; this.reconnect(); }); this.client.on("authSuccess", () => { this.reset(this.initialMetadata); }); this.client.on("joined", () => { this.handleReconnect(); }); } reset(initialMetadata) { this.initialMetadata = initialMetadata; this.reconnectAttempt = 0; if (this.reconnectTimeoutId) clearTimeout(this.reconnectTimeoutId); this.reconnectTimeoutId = null; } getLastPeerMetadata() { return this.lastLocalEndpoint?.metadata; } reconnect() { if (this.reconnectTimeoutId) return; if (this.reconnectAttempt >= this.reconnectConfig.maxAttempts) { if (!this.reconnectFailedNotificationSend) { this.reconnectFailedNotificationSend = true; } return; } if (!this.ongoingReconnection) { this.ongoingReconnection = true; this.lastLocalEndpoint = this.client.getLocalEndpoint() || null; } const timeout = this.reconnectConfig.initialDelay + this.reconnectAttempt * this.reconnectConfig.delay; this.reconnectAttempt += 1; this.reconnectTimeoutId = setTimeout(() => { this.reconnectTimeoutId = null; this.connect(this.getLastPeerMetadata() ?? this.initialMetadata); }, timeout); } handleReconnect() { if (!this.ongoingReconnection) return; if (this.lastLocalEndpoint && this.reconnectConfig.addTracksOnReconnect) { this.lastLocalEndpoint.tracks.forEach(async (track) => { if (!track.track || !track.stream) return; await this.client.addTrack(track.track, track.stream, track.rawMetadata, track.simulcastConfig, track.maxBandwidth); }); } this.lastLocalEndpoint = null; this.ongoingReconnection = false; } } export const createReconnectConfig = (config) => { if (!config) return DISABLED_RECONNECT_CONFIG; if (config === true) return DEFAULT_RECONNECT_CONFIG; return { maxAttempts: config?.maxAttempts ?? DEFAULT_RECONNECT_CONFIG.maxAttempts, initialDelay: config?.initialDelay ?? DEFAULT_RECONNECT_CONFIG.initialDelay, delay: config?.delay ?? DEFAULT_RECONNECT_CONFIG.delay, addTracksOnReconnect: config?.addTracksOnReconnect ?? DEFAULT_RECONNECT_CONFIG.addTracksOnReconnect, }; };