@aptpod/iscp-ts
Version:
iSCP 2.0 client library for TypeScript
217 lines • 12 kB
JavaScript
"use strict";
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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
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;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TransportWithReconnect = void 0;
const await_lock_1 = __importDefault(require("await-lock"));
const constant_1 = require("./constant");
const exceptions_1 = require("./exceptions");
const transport_1 = require("./transport");
const exponential_backoff_1 = require("./utils/exponential-backoff");
const resolver_1 = require("./utils/resolver");
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_1.Resolver(), "f");
__classPrivateFieldSet(this, _TransportWithReconnect_closedResolver, new resolver_1.Resolver(), "f");
__classPrivateFieldSet(this, _TransportWithReconnect_lock, {
read: new await_lock_1.default(),
write: new await_lock_1.default(),
unreliableRead: new await_lock_1.default(),
unreliableWrite: new await_lock_1.default(),
reconnect: new await_lock_1.default(),
}, "f");
__classPrivateFieldSet(this, _TransportWithReconnect_abortController, new AbortController(), "f");
}
async open() {
if (__classPrivateFieldGet(this, _TransportWithReconnect_openedResolver, "f").isDone) {
throw new exceptions_1.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 exponential_backoff_1.Jitter({
ratioCreator: Math.random,
min: constant_1.RECONNECT_JITTER_MIN,
max: constant_1.RECONNECT_JITTER_MAX,
});
const backoff = new exponential_backoff_1.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: constant_1.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 exponential_backoff_1.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 transport_1.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;
}
}
exports.TransportWithReconnect = TransportWithReconnect;
_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 exceptions_1.ISCPTransportClosedError();
}
return maybeTransport;
};
const asUnreliable = (maybeUnreliable) => {
if (!(maybeUnreliable instanceof transport_1.Unreliable)) {
throw new exceptions_1.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