UNPKG

@aptpod/iscp-ts

Version:

iSCP 2.0 client library for TypeScript

210 lines 11.5 kB
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _TransportWithReconnect_instances, _TransportWithReconnect_transportBuilder, _TransportWithReconnect_transport, _TransportWithReconnect_reconnectBaseIntervalMs, _TransportWithReconnect_reconnectMaxIntervalMs, _TransportWithReconnect_onReconnectRetryBefore, _TransportWithReconnect_onReconnectSucceeded, _TransportWithReconnect_openedResolver, _TransportWithReconnect_closedResolver, _TransportWithReconnect_lock, _TransportWithReconnect_abortController, _TransportWithReconnect_unreliableRead, _TransportWithReconnect_unreliableWrite; import AwaitLock from 'await-lock'; import { RECONNECT_JITTER_MAX, RECONNECT_JITTER_MIN, RECONNECT_NUM_OF_ATTEMPTS } from './constant'; import { ISCPException, ISCPTransportClosedError } from './exceptions'; import { Unreliable } from './transport'; import { AbortedError, ExponentialBackoff, Jitter } from './utils/exponential-backoff'; import { Resolver } from './utils/resolver'; export class TransportWithReconnect { constructor(config) { _TransportWithReconnect_instances.add(this); _TransportWithReconnect_transportBuilder.set(this, void 0); _TransportWithReconnect_transport.set(this, void 0); _TransportWithReconnect_reconnectBaseIntervalMs.set(this, void 0); _TransportWithReconnect_reconnectMaxIntervalMs.set(this, void 0); _TransportWithReconnect_onReconnectRetryBefore.set(this, void 0); _TransportWithReconnect_onReconnectSucceeded.set(this, void 0); _TransportWithReconnect_openedResolver.set(this, void 0); _TransportWithReconnect_closedResolver.set(this, void 0); _TransportWithReconnect_lock.set(this, void 0); _TransportWithReconnect_abortController.set(this, void 0); __classPrivateFieldSet(this, _TransportWithReconnect_transportBuilder, config.transportBuilder, "f"); __classPrivateFieldSet(this, _TransportWithReconnect_transport, null, "f"); __classPrivateFieldSet(this, _TransportWithReconnect_reconnectBaseIntervalMs, config.reconnectBaseIntervalMs, "f"); __classPrivateFieldSet(this, _TransportWithReconnect_reconnectMaxIntervalMs, config.reconnectMaxIntervalMs, "f"); __classPrivateFieldSet(this, _TransportWithReconnect_onReconnectRetryBefore, config.onReconnectRetryBefore, "f"); __classPrivateFieldSet(this, _TransportWithReconnect_onReconnectSucceeded, config.onReconnectSucceeded, "f"); __classPrivateFieldSet(this, _TransportWithReconnect_openedResolver, new Resolver(), "f"); __classPrivateFieldSet(this, _TransportWithReconnect_closedResolver, new Resolver(), "f"); __classPrivateFieldSet(this, _TransportWithReconnect_lock, { read: new AwaitLock(), write: new AwaitLock(), unreliableRead: new AwaitLock(), unreliableWrite: new AwaitLock(), reconnect: new AwaitLock(), }, "f"); __classPrivateFieldSet(this, _TransportWithReconnect_abortController, new AbortController(), "f"); } async open() { if (__classPrivateFieldGet(this, _TransportWithReconnect_openedResolver, "f").isDone) { throw new ISCPException('Already opened.'); } __classPrivateFieldSet(this, _TransportWithReconnect_transport, await __classPrivateFieldGet(this, _TransportWithReconnect_transportBuilder, "f").call(this), "f"); __classPrivateFieldGet(this, _TransportWithReconnect_openedResolver, "f").resolve(); } async close() { if (!__classPrivateFieldGet(this, _TransportWithReconnect_openedResolver, "f").isDone) { return; } if (__classPrivateFieldGet(this, _TransportWithReconnect_closedResolver, "f").isDone) { return; } try { __classPrivateFieldGet(this, _TransportWithReconnect_abortController, "f").abort(); await __classPrivateFieldGet(this, _TransportWithReconnect_transport, "f")?.close(); } finally { __classPrivateFieldGet(this, _TransportWithReconnect_closedResolver, "f").resolve(); await forceReleaseLock(Object.values(__classPrivateFieldGet(this, _TransportWithReconnect_lock, "f"))); } } async reconnect() { if (__classPrivateFieldGet(this, _TransportWithReconnect_closedResolver, "f").isDone) { return; } const jitter = new Jitter({ ratioCreator: Math.random, min: RECONNECT_JITTER_MIN, max: RECONNECT_JITTER_MAX, }); const backoff = new ExponentialBackoff({ run: async () => { if (__classPrivateFieldGet(this, _TransportWithReconnect_closedResolver, "f").isDone) { return; } await __classPrivateFieldGet(this, _TransportWithReconnect_transport, "f")?.close(); __classPrivateFieldSet(this, _TransportWithReconnect_transport, await __classPrivateFieldGet(this, _TransportWithReconnect_transportBuilder, "f").call(this), "f"); await __classPrivateFieldGet(this, _TransportWithReconnect_onReconnectSucceeded, "f").call(this); }, signal: __classPrivateFieldGet(this, _TransportWithReconnect_abortController, "f").signal, baseTimeoutMs: __classPrivateFieldGet(this, _TransportWithReconnect_reconnectBaseIntervalMs, "f"), maxTimeoutMs: __classPrivateFieldGet(this, _TransportWithReconnect_reconnectMaxIntervalMs, "f"), numOfAttempts: RECONNECT_NUM_OF_ATTEMPTS, jitter, }); backoff.onBeforeRetry = ({ error }) => { __classPrivateFieldGet(this, _TransportWithReconnect_onReconnectRetryBefore, "f").call(this, { error }); }; const { releaseLock } = await acquireLock([__classPrivateFieldGet(this, _TransportWithReconnect_lock, "f").reconnect]); try { const result = await backoff.start(); if (result instanceof AbortedError) { return; } if (result instanceof Error) { throw result; } } finally { await releaseLock(); } } async read() { const { releaseLock } = await acquireLock([__classPrivateFieldGet(this, _TransportWithReconnect_lock, "f").read]); try { return await asTransport(__classPrivateFieldGet(this, _TransportWithReconnect_transport, "f")).read(); } finally { await releaseLock(); } } async write(message) { const { releaseLock } = await acquireLock([__classPrivateFieldGet(this, _TransportWithReconnect_lock, "f").write]); try { await asTransport(__classPrivateFieldGet(this, _TransportWithReconnect_transport, "f")).write(message); } finally { await releaseLock(); } } getUnreliable() { const transport = asTransport(__classPrivateFieldGet(this, _TransportWithReconnect_transport, "f")); return transport instanceof Unreliable ? { read: __classPrivateFieldGet(this, _TransportWithReconnect_instances, "m", _TransportWithReconnect_unreliableRead).bind(this), write: __classPrivateFieldGet(this, _TransportWithReconnect_instances, "m", _TransportWithReconnect_unreliableWrite).bind(this), } : false; } get address() { return asTransport(__classPrivateFieldGet(this, _TransportWithReconnect_transport, "f")).address; } get negotiationParams() { return asTransport(__classPrivateFieldGet(this, _TransportWithReconnect_transport, "f")).negotiationParams; } get name() { return asTransport(__classPrivateFieldGet(this, _TransportWithReconnect_transport, "f")).name; } } _TransportWithReconnect_transportBuilder = new WeakMap(), _TransportWithReconnect_transport = new WeakMap(), _TransportWithReconnect_reconnectBaseIntervalMs = new WeakMap(), _TransportWithReconnect_reconnectMaxIntervalMs = new WeakMap(), _TransportWithReconnect_onReconnectRetryBefore = new WeakMap(), _TransportWithReconnect_onReconnectSucceeded = new WeakMap(), _TransportWithReconnect_openedResolver = new WeakMap(), _TransportWithReconnect_closedResolver = new WeakMap(), _TransportWithReconnect_lock = new WeakMap(), _TransportWithReconnect_abortController = new WeakMap(), _TransportWithReconnect_instances = new WeakSet(), _TransportWithReconnect_unreliableRead = // // Private Methods // async function _TransportWithReconnect_unreliableRead() { const { releaseLock } = await acquireLock([__classPrivateFieldGet(this, _TransportWithReconnect_lock, "f").unreliableRead]); try { const transport = asTransport(__classPrivateFieldGet(this, _TransportWithReconnect_transport, "f")); const { reader } = asUnreliable(transport).getUnreliable(); return await reader.read(); } finally { await releaseLock(); } }, _TransportWithReconnect_unreliableWrite = async function _TransportWithReconnect_unreliableWrite(message) { const { releaseLock } = await acquireLock([__classPrivateFieldGet(this, _TransportWithReconnect_lock, "f").unreliableWrite]); try { const transport = asTransport(__classPrivateFieldGet(this, _TransportWithReconnect_transport, "f")); const { writer } = asUnreliable(transport).getUnreliable(); return await writer.write(message); } finally { await releaseLock(); } }; // // Static Functions // const asTransport = (maybeTransport) => { if (!maybeTransport) { throw new ISCPTransportClosedError(); } return maybeTransport; }; const asUnreliable = (maybeUnreliable) => { if (!(maybeUnreliable instanceof Unreliable)) { throw new ISCPException('Unsupported unreliable transport.'); } return maybeUnreliable; }; const acquireLock = async (awaitLocks) => { for (const awaitLock of awaitLocks) { await awaitLock.acquireAsync(); } const releaseLock = async () => { for (const awaitLock of awaitLocks) { awaitLock.release(); } }; return { releaseLock, }; }; const forceReleaseLock = async (awaitLocks) => { for (const awaitLock of awaitLocks) { if (awaitLock.acquired) { awaitLock.release(); } } }; //# sourceMappingURL=transport-with-reconnect.js.map