@aptpod/iscp-ts
Version:
iSCP 2.0 client library for TypeScript
895 lines • 46.1 kB
JavaScript
"use strict";
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 __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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _Conn_instances, _Conn_nodeId, _Conn_protocolVersion, _Conn_pingInterval, _Conn_pingTimeout, _Conn_projectUuid, _Conn_tokenSource, _Conn_reqSequence, _Conn_streamSequence, _Conn_logger, _Conn_encoding, _Conn_transport, _Conn_internalUpstreamMap, _Conn_internalDownstreamMap, _Conn_metadataInternalDownstreamMap, _Conn_abortController, _Conn_wireConfig, _Conn_wire, _Conn_autoReconnect, _Conn_disconnectedEvent, _Conn_closedResolver, _Conn_connReconnectLock, _Conn_transportReconnectLock, _Conn_closeLock, _Conn_closeRequiredResolver, _Conn_downstreamReplyCallTransformStreamMap, _Conn_callEvent, _Conn_replyCallEvent, _Conn_reconnectingEvent, _Conn_reconnectedEvent, _Conn_run, _Conn_createWire, _Conn_connect, _Conn_reconnect, _Conn_handleUpstreamChunkAck, _Conn_handleDownstreamChunk, _Conn_handleDownstreamMetadata, _Conn_handleDownstreamChunkAckComplete, _Conn_handleDownstreamCall, _Conn_sendMetadata, _Conn_close;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Conn = exports.ReconnectingEvent = exports.DisconnectedEvent = void 0;
const await_lock_1 = __importDefault(require("await-lock"));
const web_streams_polyfill_1 = require("web-streams-polyfill");
const encoding_1 = require("./encoding");
const message_1 = require("./message");
const transport_1 = require("./transport");
const exceptions_1 = require("./exceptions");
const constant_1 = require("./constant");
const downstream_1 = require("./message/downstream");
const common_1 = require("./message/common");
const model_1 = require("./model");
const upstream_1 = require("./upstream");
const downstream_2 = require("./downstream");
const sequence_1 = require("./sequence");
const flush_policy_1 = require("./flush-policy");
const stream_reader_iterator_1 = require("./utils/stream-reader-iterator");
const logger_1 = require("./logger");
const message_io_1 = require("./message-io");
const wire_1 = require("./wire");
const typed_event_1 = require("./utils/typed-event");
const transport_with_reconnect_1 = require("./transport-with-reconnect");
const resolver_1 = require("./utils/resolver");
const uuid_1 = require("./utils/uuid");
const exceptions_2 = require("./exceptions/exceptions");
const PROTOCOL_VERSION = '2.0.0';
/**
* iSCPを切断した時のイベントです。
* @category Connection
*/
class DisconnectedEvent {
constructor(init) {
this.error = init.error;
}
}
exports.DisconnectedEvent = DisconnectedEvent;
/**
* iSCPの再接続を開始した時のイベントです。
* @category Connection
*/
class ReconnectingEvent {
constructor(init) {
this.error = init.error;
}
}
exports.ReconnectingEvent = ReconnectingEvent;
/**
* iSCPのコネクションを表すクラスです。
*
* @category Connection
*
* @attention
* このクラスのオブジェクトは、必ず{@link Conn}の{@link Conn.connect}を使用して生成してください。
*
* @example
* ```ts
* const example = async () => {
* const conn = await Conn.connect(...)
* try {
* // ...
* } finally {
* await conn.close()
* }
* }
* ```
*/
class Conn {
/**
* iSCP接続を行い{@link Conn}を返却します。
*/
static async connect(config) {
const encodingName = config.encoding ?? Conn.DEFAULT_ENCODING_NAME;
const negotiationParams = new transport_1.NegotiationParams();
negotiationParams.enc = encodingName;
const encoding = toEncodingByName(encodingName);
const conn = new Conn({
logLevel: config.logLevel,
address: config.address,
negotiationParams,
connector: config.connector,
encoding,
nodeId: config.nodeId,
protocolVersion: PROTOCOL_VERSION,
pingInterval: config.pingInterval ?? Conn.DEFAULT_PING_INTERVAL,
pingTimeout: config.pingTimeout ?? Conn.DEFAULT_PING_TIMEOUT,
projectUuid: config.projectUuid,
tokenSource: config.tokenSource,
autoReconnect: config.autoReconnect ?? Conn.DEFAULT_AUTO_RECONNECT,
reconnectBaseInterval: config.reconnectBaseInterval ?? Conn.DEFAULT_RECONNECT_BASE_INTERVAL,
reconnectMaxInterval: config.reconnectMaxInterval ?? Conn.DEFAULT_RECONNECT_MAX_INTERVAL,
});
await __classPrivateFieldGet(conn, _Conn_instances, "m", _Conn_run).call(conn);
return conn;
}
/**
* @internal
*/
constructor(config) {
_Conn_instances.add(this);
// from config
_Conn_nodeId.set(this, void 0);
_Conn_protocolVersion.set(this, void 0);
_Conn_pingInterval.set(this, void 0);
_Conn_pingTimeout.set(this, void 0);
_Conn_projectUuid.set(this, void 0);
_Conn_tokenSource.set(this, void 0);
// sequence
_Conn_reqSequence.set(this, void 0);
_Conn_streamSequence.set(this, void 0);
_Conn_logger.set(this, void 0);
_Conn_encoding.set(this, void 0);
_Conn_transport.set(this, void 0);
_Conn_internalUpstreamMap.set(this, void 0);
_Conn_internalDownstreamMap.set(this, void 0);
_Conn_metadataInternalDownstreamMap.set(this, void 0);
_Conn_abortController.set(this, void 0);
_Conn_wireConfig.set(this, void 0);
_Conn_wire.set(this, void 0);
_Conn_autoReconnect.set(this, void 0);
_Conn_disconnectedEvent.set(this, void 0);
_Conn_closedResolver.set(this, void 0);
_Conn_connReconnectLock.set(this, void 0);
_Conn_transportReconnectLock.set(this, void 0);
_Conn_closeLock.set(this, void 0);
_Conn_closeRequiredResolver.set(this, void 0);
_Conn_downstreamReplyCallTransformStreamMap.set(this, void 0);
_Conn_callEvent.set(this, void 0);
_Conn_replyCallEvent.set(this, void 0);
_Conn_reconnectingEvent.set(this, void 0);
_Conn_reconnectedEvent.set(this, void 0);
// from config
__classPrivateFieldSet(this, _Conn_nodeId, config.nodeId, "f");
__classPrivateFieldSet(this, _Conn_protocolVersion, config.protocolVersion, "f");
__classPrivateFieldSet(this, _Conn_pingInterval, config.pingInterval, "f");
__classPrivateFieldSet(this, _Conn_pingTimeout, config.pingTimeout, "f");
__classPrivateFieldSet(this, _Conn_projectUuid, config.projectUuid, "f");
__classPrivateFieldSet(this, _Conn_tokenSource, config.tokenSource, "f");
// sequence
__classPrivateFieldSet(this, _Conn_reqSequence, sequence_1.Sequence.forRequestId(), "f");
__classPrivateFieldSet(this, _Conn_streamSequence, sequence_1.Sequence.forStreamId(), "f");
__classPrivateFieldSet(this, _Conn_logger, new logger_1.LoggerConsole({
logLevel: config.logLevel ?? model_1.LOG_LEVEL.WARNING,
}), "f");
__classPrivateFieldSet(this, _Conn_encoding, config.encoding, "f");
__classPrivateFieldSet(this, _Conn_transport, new transport_with_reconnect_1.TransportWithReconnect({
transportBuilder: async () => await config.connector.connect(config.address, config.negotiationParams),
reconnectBaseIntervalMs: config.reconnectBaseInterval * 1e3,
reconnectMaxIntervalMs: config.reconnectMaxInterval * 1e3,
onReconnectRetryBefore: async ({ error }) => {
__classPrivateFieldGet(this, _Conn_reconnectingEvent, "f").emit(new ReconnectingEvent({ error }));
},
onReconnectSucceeded: async () => {
await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_createWire).call(this, asWireConfig(__classPrivateFieldGet(this, _Conn_wireConfig, "f")));
await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_connect).call(this);
},
}), "f");
__classPrivateFieldSet(this, _Conn_internalUpstreamMap, new Map(), "f");
__classPrivateFieldSet(this, _Conn_internalDownstreamMap, new Map(), "f");
__classPrivateFieldSet(this, _Conn_metadataInternalDownstreamMap, new Map(), "f");
__classPrivateFieldSet(this, _Conn_abortController, new AbortController(), "f");
__classPrivateFieldSet(this, _Conn_autoReconnect, config.autoReconnect, "f");
__classPrivateFieldSet(this, _Conn_disconnectedEvent, new typed_event_1.TypedEvent(), "f");
__classPrivateFieldSet(this, _Conn_closedResolver, new resolver_1.Resolver(), "f");
__classPrivateFieldSet(this, _Conn_connReconnectLock, new await_lock_1.default(), "f");
__classPrivateFieldSet(this, _Conn_transportReconnectLock, new await_lock_1.default(), "f");
__classPrivateFieldSet(this, _Conn_closeLock, new await_lock_1.default(), "f");
__classPrivateFieldSet(this, _Conn_closeRequiredResolver, new resolver_1.Resolver(), "f");
__classPrivateFieldSet(this, _Conn_downstreamReplyCallTransformStreamMap, new Map(), "f");
__classPrivateFieldSet(this, _Conn_callEvent, new typed_event_1.TypedEvent(), "f");
__classPrivateFieldSet(this, _Conn_replyCallEvent, new typed_event_1.TypedEvent(), "f");
__classPrivateFieldSet(this, _Conn_reconnectingEvent, new typed_event_1.TypedEvent(), "f");
__classPrivateFieldSet(this, _Conn_reconnectedEvent, new typed_event_1.TypedEvent(), "f");
}
/**
* ノードIDを取得します。
* @returns ノードID
*/
get nodeId() {
return __classPrivateFieldGet(this, _Conn_nodeId, "f");
}
/**
* Ping間隔(秒)を取得します。
* @returns Ping間隔(秒)
*/
get pingInterval() {
return __classPrivateFieldGet(this, _Conn_pingInterval, "f");
}
/**
* Pingタイムアウト(秒)を取得します。
* @returns Pingタイムアウト(秒)
*/
get pingTimeout() {
return __classPrivateFieldGet(this, _Conn_pingTimeout, "f");
}
/**
* プロジェクトUUIDを取得します。
* @returns プロジェクトUUID
*/
get projectUuid() {
return __classPrivateFieldGet(this, _Conn_projectUuid, "f");
}
/**
* アドレスを取得します。
* @returns アドレス
*/
get address() {
return __classPrivateFieldGet(this, _Conn_transport, "f").address;
}
/**
* エンコーディング名を取得します。
* @returns エンコーディング名
*/
get encoding() {
return __classPrivateFieldGet(this, _Conn_encoding, "f").name;
}
/**
* トランスポート名を取得します。
* @returns トランスポート名
*/
get transport() {
return __classPrivateFieldGet(this, _Conn_transport, "f").name;
}
/**
* アップストリームを開きます。
* @returns アップストリーム
*/
async openUpstream(config) {
const expiryInterval = config.expiryInterval ?? Conn.DEFAULT_EXPIRY_INTERVAL;
const qos = config.qos ?? Conn.DEFAULT_QOS;
const ackInterval = config.ackInterval ?? Conn.DEFAULT_ACK_INTERVAL;
const persist = config.persist ?? Conn.DEFAULT_PERSIST;
const flushPolicy = config.flushPolicy ?? flush_policy_1.FlushPolicy.intervalOrBufferSize();
const closeTimeout = config.closeTimeout ?? Conn.DEFAULT_CLOSE_TIMEOUT;
const closeSession = config.closeSession ?? Conn.DEFAULT_CLOSE_SESSION;
if (!__classPrivateFieldGet(this, _Conn_wire, "f")) {
throw new exceptions_2.ISCPException('wire is invalid.');
}
const response = await __classPrivateFieldGet(this, _Conn_wire, "f").openUpstream(new message_1.UpstreamOpenRequest({
requestId: 0,
sessionId: config.sessionId,
expiryInterval,
dataIds: config.dataIds ?? [],
qos,
ackInterval,
extensionFields: new message_1.UpstreamOpenRequestExtensionFields({ persist }),
}));
if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) {
throw new exceptions_1.ISCPFailedMessageError(response);
}
const transformChunkAck = new web_streams_polyfill_1.TransformStream();
const transformReopen = new web_streams_polyfill_1.TransformStream();
const upstream = await upstream_1.Upstream.start({
logger: __classPrivateFieldGet(this, _Conn_logger, "f"),
id: response.assignedStreamId,
idAlias: response.assignedStreamIdAlias,
sessionId: config.sessionId,
dataIdAliases: response.dataIdAliases,
serverTime: response.serverTime,
closeTimeout,
ackInterval,
expiryInterval,
qos,
flushPolicy,
persist,
closeSession,
resumeRequester: async (request) => {
if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) {
throw new exceptions_2.ISCPReconnectingError();
}
return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).resumeUpstream(request);
},
closeRequester: async (request) => {
if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) {
throw new exceptions_2.ISCPReconnectingError();
}
return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).closeUpstream(request);
},
chunkSender: async (message) => {
if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) {
throw new exceptions_2.ISCPReconnectingError();
}
return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).sendUpstreamChunk(message);
},
chunkAckStreamReader: transformChunkAck.readable.getReader(),
reopenStreamReader: transformReopen.readable.getReader(),
});
const internalUpstream = new InternalUpstream({
chunkAckWriter: transformChunkAck.writable.getWriter(),
reopenWriter: transformReopen.writable.getWriter(),
close: upstream.close.bind(upstream),
});
__classPrivateFieldGet(this, _Conn_internalUpstreamMap, "f").set(response.assignedStreamIdAlias, internalUpstream);
upstream.waitClosed().then(() => {
__classPrivateFieldGet(this, _Conn_internalUpstreamMap, "f").delete(response.assignedStreamIdAlias);
});
return upstream;
}
/**
* ダウンストリームを開きます。
* @returns ダウンストリーム
*/
async openDownstream(config) {
const streamIdAlias = __classPrivateFieldGet(this, _Conn_streamSequence, "f").next();
const dataIdAliasSequence = sequence_1.Sequence.forDataIdAlias();
const qos = config.qos ?? Conn.DEFAULT_QOS;
const expiryInterval = config.expiryInterval ?? Conn.DEFAULT_EXPIRY_INTERVAL;
const ackInterval = config.ackInterval ?? Conn.DEFAULT_ACK_INTERVAL;
const omitEmptyChunk = config.omitEmptyChunk ?? Conn.DEFAULT_OMIT_EMPTY_CHUNK;
const dataIdAliases = (config.dataIds ?? []).reduce((prev, cur) => {
const alias = dataIdAliasSequence.next();
return { ...prev, [alias]: cur };
}, {});
if (!__classPrivateFieldGet(this, _Conn_wire, "f")) {
throw new exceptions_2.ISCPException('wire is invalid.');
}
const response = await __classPrivateFieldGet(this, _Conn_wire, "f").openDownstream(new downstream_1.DownstreamOpenRequest({
requestId: 0,
desiredStreamIdAlias: streamIdAlias,
downstreamFilters: config.filters,
expiryInterval,
dataIdAliases,
qos,
omitEmptyChunk,
extensionFields: new downstream_1.DownstreamOpenRequestExtensionFields(),
}));
if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) {
throw new exceptions_1.ISCPFailedMessageError(response);
}
const transformChunk = new web_streams_polyfill_1.TransformStream();
const transformChunkAckComplete = new web_streams_polyfill_1.TransformStream();
const transformMetadata = new web_streams_polyfill_1.TransformStream();
const transformReopen = new web_streams_polyfill_1.TransformStream();
const downstream = await downstream_2.Downstream.start({
logger: __classPrivateFieldGet(this, _Conn_logger, "f"),
id: response.assignedStreamId,
idAlias: streamIdAlias,
serverTime: response.serverTime,
qos,
expiryInterval,
filters: config.filters,
dataIdAliases,
dataIdAliasSequence,
ackInterval,
omitEmptyChunk,
resumeRequester: async (request) => {
if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) {
throw new exceptions_2.ISCPReconnectingError();
}
return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).resumeDownstream(request);
},
closeRequester: async (request) => {
if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) {
throw new exceptions_2.ISCPReconnectingError();
}
return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).closeDownstream(request);
},
chunkAckSender: async (message) => {
if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) {
throw new exceptions_2.ISCPReconnectingError();
}
return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).sendDownstreamChunkAck(message);
},
metadataAckSender: async (metadata) => {
if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) {
throw new exceptions_2.ISCPReconnectingError();
}
return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).sendDownstreamMetadataAck(metadata);
},
chunkIterator: new stream_reader_iterator_1.StreamReaderIterator(transformChunk.readable.getReader()),
chunkAckCompleteIterator: new stream_reader_iterator_1.StreamReaderIterator(transformChunkAckComplete.readable.getReader()),
metadataIterator: new stream_reader_iterator_1.StreamReaderIterator(transformMetadata.readable.getReader()),
reopenIterator: new stream_reader_iterator_1.StreamReaderIterator(transformReopen.readable.getReader()),
});
const internalDownstream = new InternalDownstream({
chunkWriter: transformChunk.writable.getWriter(),
chunkAckCompleteWriter: transformChunkAckComplete.writable.getWriter(),
metadataWriter: transformMetadata.writable.getWriter(),
reopenWriter: transformReopen.writable.getWriter(),
close: downstream.close.bind(downstream),
});
__classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f").set(streamIdAlias, internalDownstream);
const sourceNodeIds = [...new Set(config.filters.map(({ sourceNodeId }) => sourceNodeId))];
for (const sourceNodeId of sourceNodeIds) {
let downstreamMap = __classPrivateFieldGet(this, _Conn_metadataInternalDownstreamMap, "f").get(sourceNodeId);
if (!downstreamMap) {
downstreamMap = new Map();
__classPrivateFieldGet(this, _Conn_metadataInternalDownstreamMap, "f").set(sourceNodeId, downstreamMap);
}
downstreamMap.set(streamIdAlias, internalDownstream);
}
downstream.waitClosed().then(() => {
__classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f").delete(streamIdAlias);
for (const sourceNodeId of sourceNodeIds) {
__classPrivateFieldGet(this, _Conn_metadataInternalDownstreamMap, "f").get(sourceNodeId)?.delete(streamIdAlias);
}
});
return downstream;
}
/**
* E2Eコールを送信します。
* @param upstreamCall アップストリームコール。
* @returns コールID。
*/
async sendCall(upstreamCall) {
const wire = asWire(__classPrivateFieldGet(this, _Conn_wire, "f"));
const callId = (0, uuid_1.randomUUIDv4)();
const response = await wire.sendUpstreamCall(new message_1.UpstreamCall({
callId,
requestCallId: '',
destinationNodeId: upstreamCall.destinationNodeId,
name: upstreamCall.name,
type: upstreamCall.type,
payload: upstreamCall.payload,
extensionFields: new message_1.UpstreamCallExtensionFields(),
}));
if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) {
throw new exceptions_1.ISCPFailedMessageError(response);
}
return callId;
}
/**
* E2Eコールのリプライを送信します。
* @param replyCall アップストリームリプライコール。
* @returns コールID。
*/
async sendReplyCall(replyCall) {
const wire = asWire(__classPrivateFieldGet(this, _Conn_wire, "f"));
const callId = (0, uuid_1.randomUUIDv4)();
const response = await wire.sendUpstreamCall(new message_1.UpstreamCall({
callId,
requestCallId: replyCall.requestCallId,
destinationNodeId: replyCall.destinationNodeId,
name: replyCall.name,
type: replyCall.type,
payload: replyCall.payload,
extensionFields: new message_1.UpstreamCallExtensionFields(),
}));
if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) {
throw new exceptions_1.ISCPFailedMessageError(response);
}
return callId;
}
/**
* E2Eコールを送信し、リプライコールを受信するまで待ちます。
* @param upstreamCall アップストリームコール。
* @returns ダウンストリームリプライコール
*/
async sendCallAndWaitReplyCall(upstreamCall) {
const wire = asWire(__classPrivateFieldGet(this, _Conn_wire, "f"));
const callId = (0, uuid_1.randomUUIDv4)();
try {
const transformStream = new web_streams_polyfill_1.TransformStream();
__classPrivateFieldGet(this, _Conn_downstreamReplyCallTransformStreamMap, "f").set(callId, transformStream);
const response = await wire.sendUpstreamCall(new message_1.UpstreamCall({
callId,
requestCallId: '',
destinationNodeId: upstreamCall.destinationNodeId,
name: upstreamCall.name,
type: upstreamCall.type,
payload: upstreamCall.payload,
extensionFields: new message_1.UpstreamCallExtensionFields(),
}));
if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) {
throw new exceptions_1.ISCPFailedMessageError(response);
}
const readDownstreamReplyCall = await transformStream.readable.getReader().read();
if (readDownstreamReplyCall instanceof exceptions_2.ISCPTimeoutError) {
throw readDownstreamReplyCall;
}
if (readDownstreamReplyCall.done) {
throw new exceptions_2.ISCPException('Failed to read downstreamReplyCall');
}
return readDownstreamReplyCall.value;
}
finally {
__classPrivateFieldGet(this, _Conn_downstreamReplyCallTransformStreamMap, "f").delete(callId);
}
}
/**
* 基準時刻を送信します。
* @param baseTime 基準時刻。
* @param options 基準時刻を送信する際のオプションを指定します。
*/
async sendBaseTime(baseTime, options) {
await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_sendMetadata).call(this, baseTime, {
persist: options?.persist ?? Conn.DEFAULT_SEND_BASE_TIME_OPTIONS_PERSIST,
});
}
/**
* コネクションを閉じます。
*/
async close() {
__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").resolve();
await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_close).call(this);
}
/**
* コネクションが閉じるまで待機します。
*/
async waitClosed() {
await __classPrivateFieldGet(this, _Conn_closedResolver, "f").wait();
}
addEventListener(name, listener, options) {
switch (name) {
case Conn.EVENT.CALL:
options?.once ? __classPrivateFieldGet(this, _Conn_callEvent, "f").once(listener) : __classPrivateFieldGet(this, _Conn_callEvent, "f").on(listener);
return;
case Conn.EVENT.REPLY_CALL:
options?.once ? __classPrivateFieldGet(this, _Conn_replyCallEvent, "f").once(listener) : __classPrivateFieldGet(this, _Conn_replyCallEvent, "f").on(listener);
return;
case Conn.EVENT.DISCONNECTED:
options?.once ? __classPrivateFieldGet(this, _Conn_disconnectedEvent, "f").once(listener) : __classPrivateFieldGet(this, _Conn_disconnectedEvent, "f").on(listener);
return;
case Conn.EVENT.RECONNECTING:
options?.once ? __classPrivateFieldGet(this, _Conn_reconnectingEvent, "f").once(listener) : __classPrivateFieldGet(this, _Conn_reconnectingEvent, "f").on(listener);
return;
case Conn.EVENT.RECONNECTED:
options?.once ? __classPrivateFieldGet(this, _Conn_reconnectedEvent, "f").once(listener) : __classPrivateFieldGet(this, _Conn_reconnectedEvent, "f").on(listener);
return;
default:
throw new exceptions_2.ISCPException('Unrecognized EventName.');
}
}
removeEventListener(name, listener) {
switch (name) {
case Conn.EVENT.CALL:
__classPrivateFieldGet(this, _Conn_callEvent, "f").off(listener);
return;
case Conn.EVENT.REPLY_CALL:
__classPrivateFieldGet(this, _Conn_replyCallEvent, "f").off(listener);
return;
case Conn.EVENT.DISCONNECTED:
__classPrivateFieldGet(this, _Conn_disconnectedEvent, "f").off(listener);
return;
case Conn.EVENT.RECONNECTING:
__classPrivateFieldGet(this, _Conn_reconnectingEvent, "f").off(listener);
return;
case Conn.EVENT.RECONNECTED:
__classPrivateFieldGet(this, _Conn_reconnectedEvent, "f").off(listener);
return;
default:
throw new exceptions_2.ISCPException('Unrecognized EventName.');
}
}
}
exports.Conn = Conn;
_Conn_nodeId = new WeakMap(), _Conn_protocolVersion = new WeakMap(), _Conn_pingInterval = new WeakMap(), _Conn_pingTimeout = new WeakMap(), _Conn_projectUuid = new WeakMap(), _Conn_tokenSource = new WeakMap(), _Conn_reqSequence = new WeakMap(), _Conn_streamSequence = new WeakMap(), _Conn_logger = new WeakMap(), _Conn_encoding = new WeakMap(), _Conn_transport = new WeakMap(), _Conn_internalUpstreamMap = new WeakMap(), _Conn_internalDownstreamMap = new WeakMap(), _Conn_metadataInternalDownstreamMap = new WeakMap(), _Conn_abortController = new WeakMap(), _Conn_wireConfig = new WeakMap(), _Conn_wire = new WeakMap(), _Conn_autoReconnect = new WeakMap(), _Conn_disconnectedEvent = new WeakMap(), _Conn_closedResolver = new WeakMap(), _Conn_connReconnectLock = new WeakMap(), _Conn_transportReconnectLock = new WeakMap(), _Conn_closeLock = new WeakMap(), _Conn_closeRequiredResolver = new WeakMap(), _Conn_downstreamReplyCallTransformStreamMap = new WeakMap(), _Conn_callEvent = new WeakMap(), _Conn_replyCallEvent = new WeakMap(), _Conn_reconnectingEvent = new WeakMap(), _Conn_reconnectedEvent = new WeakMap(), _Conn_instances = new WeakSet(), _Conn_run = async function _Conn_run() {
await __classPrivateFieldGet(this, _Conn_transport, "f").open();
const messageIO = new message_io_1.MessageIO({
encoding: __classPrivateFieldGet(this, _Conn_encoding, "f"),
reader: __classPrivateFieldGet(this, _Conn_transport, "f"),
writer: __classPrivateFieldGet(this, _Conn_transport, "f"),
logger: __classPrivateFieldGet(this, _Conn_logger, "f"),
});
const unreliableTransport = __classPrivateFieldGet(this, _Conn_transport, "f").getUnreliable();
const unreliableMessageIO = unreliableTransport
? new message_io_1.MessageIO({
encoding: __classPrivateFieldGet(this, _Conn_encoding, "f"),
reader: unreliableTransport,
writer: unreliableTransport,
logger: __classPrivateFieldGet(this, _Conn_logger, "f"),
})
: undefined;
__classPrivateFieldSet(this, _Conn_wireConfig, {
requestSequence: __classPrivateFieldGet(this, _Conn_reqSequence, "f"),
reader: messageIO.read.bind(messageIO),
writer: messageIO.write.bind(messageIO),
unreliableReader: unreliableMessageIO?.read?.bind(unreliableMessageIO),
unreliableWriter: unreliableMessageIO?.write?.bind(unreliableMessageIO),
pingInterval: __classPrivateFieldGet(this, _Conn_pingInterval, "f"),
pingTimeout: __classPrivateFieldGet(this, _Conn_pingTimeout, "f"),
logger: __classPrivateFieldGet(this, _Conn_logger, "f"),
}, "f");
await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_createWire).call(this, __classPrivateFieldGet(this, _Conn_wireConfig, "f"));
await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_connect).call(this);
}, _Conn_createWire = async function _Conn_createWire(wireConfig) {
const wire = new wire_1.Wire(wireConfig);
__classPrivateFieldSet(this, _Conn_wire, wire, "f");
wire.onDownstreamChunk = __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_handleDownstreamChunk).bind(this);
wire.onDownstreamMetadata = __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_handleDownstreamMetadata).bind(this);
wire.onDownstreamChunkAckComplete = __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_handleDownstreamChunkAckComplete).bind(this);
wire.onUpstreamChunkAck = __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_handleUpstreamChunkAck).bind(this);
wire.onDownstreamCall = __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_handleDownstreamCall).bind(this);
wire.onPingTimeout = async () => {
const overwriteError = new exceptions_2.ISCPTimeoutError('ping timeout.');
__classPrivateFieldGet(this, _Conn_instances, "m", _Conn_reconnect).call(this, overwriteError);
};
wire.onDisconnect = async (message) => {
if (message.resultCode === message_1.RESULT_CODE.PING_TIMEOUT) {
const overwriteError = new exceptions_2.ISCPTimeoutError('ping timeout.');
__classPrivateFieldGet(this, _Conn_instances, "m", _Conn_reconnect).call(this, overwriteError);
return;
}
const overwriteError = new exceptions_2.ISCPTransportClosedError(`${message.resultString} [code=${message.resultCode}]`);
__classPrivateFieldGet(this, _Conn_instances, "m", _Conn_close).call(this, overwriteError);
};
wire.onError = async () => { };
wire.start().catch((error) => {
const overwriteError = error instanceof Error ? error : new Error(String(error));
__classPrivateFieldGet(this, _Conn_instances, "m", _Conn_close).call(this, overwriteError);
});
}, _Conn_connect = async function _Conn_connect() {
if (!__classPrivateFieldGet(this, _Conn_wire, "f")) {
throw new Error('invalid wire.');
}
const response = await __classPrivateFieldGet(this, _Conn_wire, "f").connect(new message_1.ConnectRequest({
requestId: 0,
nodeId: __classPrivateFieldGet(this, _Conn_nodeId, "f") ?? constant_1.DEFAULT_NODE_ID,
protocolVersion: __classPrivateFieldGet(this, _Conn_protocolVersion, "f"),
pingInterval: __classPrivateFieldGet(this, _Conn_pingInterval, "f"),
pingTimeout: __classPrivateFieldGet(this, _Conn_pingTimeout, "f"),
extensionFields: new message_1.ConnectRequestExtensionFields({
accessToken: __classPrivateFieldGet(this, _Conn_tokenSource, "f") ? await __classPrivateFieldGet(this, _Conn_tokenSource, "f").call(this) : constant_1.DEFAULT_TOKEN_SOURCE,
intdash: new message_1.IntdashExtensionFields({
projectUuid: __classPrivateFieldGet(this, _Conn_projectUuid, "f") ?? constant_1.NIL_UUID,
}),
}),
}));
if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) {
throw new exceptions_1.ISCPFailedMessageError(response);
}
}, _Conn_reconnect = async function _Conn_reconnect(overwriteError) {
if (__classPrivateFieldGet(this, _Conn_closedResolver, "f").isDone) {
return;
}
if (!__classPrivateFieldGet(this, _Conn_autoReconnect, "f")) {
await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_close).call(this, overwriteError);
return;
}
await __classPrivateFieldGet(this, _Conn_connReconnectLock, "f").acquireAsync();
try {
// @memo
// 初回のエラーはここでemitする
// transport.reconnect 内部のリトライエラーは、transport.onReconnectBeforeRetryで通知される
__classPrivateFieldGet(this, _Conn_reconnectingEvent, "f").emit({ error: overwriteError });
await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).cancel();
await __classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquireAsync();
await __classPrivateFieldGet(this, _Conn_transport, "f").reconnect();
__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").release();
for (const upstream of __classPrivateFieldGet(this, _Conn_internalUpstreamMap, "f").values()) {
await upstream.reopenWriter.write();
}
for (const downstream of __classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f").values()) {
await downstream.reopenWriter.write();
}
__classPrivateFieldGet(this, _Conn_reconnectedEvent, "f").emit();
}
catch (error) {
if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) {
__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").release();
}
const newOverwriteError = error instanceof Error ? error : new Error(String(error));
await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_close).call(this, newOverwriteError);
}
finally {
__classPrivateFieldGet(this, _Conn_connReconnectLock, "f").release();
}
}, _Conn_handleUpstreamChunkAck = async function _Conn_handleUpstreamChunkAck(chunkAck) {
if (!__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").isDone) {
await __classPrivateFieldGet(this, _Conn_internalUpstreamMap, "f").get(chunkAck.streamIdAlias)?.chunkAckWriter.write(chunkAck);
}
}, _Conn_handleDownstreamChunk = async function _Conn_handleDownstreamChunk(chunk) {
if (!__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").isDone) {
await __classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f").get(chunk.streamIdAlias)?.chunkWriter.write(chunk);
}
}, _Conn_handleDownstreamMetadata = async function _Conn_handleDownstreamMetadata(metadata) {
if (!__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").isDone) {
const downstreams = [...(__classPrivateFieldGet(this, _Conn_metadataInternalDownstreamMap, "f").get(metadata.sourceNodeId)?.values() ?? [])];
for (const downstream of downstreams) {
await downstream.metadataWriter.write(metadata);
}
}
}, _Conn_handleDownstreamChunkAckComplete = async function _Conn_handleDownstreamChunkAckComplete(chunkAckComplete) {
if (!__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").isDone) {
await __classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f")
.get(chunkAckComplete.streamIdAlias)
?.chunkAckCompleteWriter.write(chunkAckComplete);
}
}, _Conn_handleDownstreamCall = async function _Conn_handleDownstreamCall(downstreamCall) {
if (!__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").isDone) {
if (downstreamCall.requestCallId === '') {
const modelDownstreamCall = new model_1.DownstreamCall({
callId: downstreamCall.callId,
sourceNodeId: downstreamCall.sourceNodeId,
name: downstreamCall.name,
type: downstreamCall.type,
payload: downstreamCall.payload,
});
__classPrivateFieldGet(this, _Conn_callEvent, "f").emit(modelDownstreamCall);
return;
}
const modelDownstreamReplyCall = new model_1.DownstreamReplyCall({
requestCalId: downstreamCall.requestCallId,
sourceNodeId: downstreamCall.sourceNodeId,
name: downstreamCall.name,
type: downstreamCall.type,
payload: downstreamCall.payload,
});
__classPrivateFieldGet(this, _Conn_replyCallEvent, "f").emit(modelDownstreamReplyCall);
const transformStream = __classPrivateFieldGet(this, _Conn_downstreamReplyCallTransformStreamMap, "f").get(downstreamCall.requestCallId);
if (transformStream) {
const writer = transformStream.writable.getWriter();
await writer.write(modelDownstreamReplyCall);
await writer.close();
}
}
}, _Conn_sendMetadata = async function _Conn_sendMetadata(metadata, options) {
const wire = asWire(__classPrivateFieldGet(this, _Conn_wire, "f"));
const response = await wire.upstreamMetadata(new message_1.UpstreamMetadata({
requestId: 0,
metadata,
extensionFields: new message_1.UpstreamMetadataExtensionFields({
persist: options.persist,
}),
}));
if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) {
throw new exceptions_1.ISCPFailedMessageError(response);
}
}, _Conn_close = async function _Conn_close(overwriteError) {
// async-lock
// closed なら true なら抜ける
await __classPrivateFieldGet(this, _Conn_closeLock, "f").acquireAsync();
if (__classPrivateFieldGet(this, _Conn_closedResolver, "f").isDone) {
return;
}
let errorToThrow = overwriteError;
try {
for (const upstream of __classPrivateFieldGet(this, _Conn_internalUpstreamMap, "f").values()) {
await upstream.dispose();
}
for (const downstream of __classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f").values()) {
await downstream.dispose();
}
await __classPrivateFieldGet(this, _Conn_wire, "f")?.disconnect(new message_1.Disconnect({
resultCode: message_1.RESULT_CODE.NORMAL_CLOSURE,
resultString: 'NORMAL_CLOSURE',
extensionFields: new message_1.DisconnectExtensionFields(),
}));
}
catch (error) {
__classPrivateFieldGet(this, _Conn_logger, "f").warn(constant_1.LOGGER_TAG.CONN, error);
errorToThrow = error instanceof Error ? error : new Error(String(error));
}
try {
await __classPrivateFieldGet(this, _Conn_wire, "f")?.cancel();
__classPrivateFieldGet(this, _Conn_abortController, "f").abort();
await __classPrivateFieldGet(this, _Conn_transport, "f").close();
}
catch (error) {
__classPrivateFieldGet(this, _Conn_logger, "f").error(constant_1.LOGGER_TAG.CONN, error);
errorToThrow = error instanceof Error ? error : new Error(String(error));
}
finally {
__classPrivateFieldGet(this, _Conn_disconnectedEvent, "f").emit(new DisconnectedEvent({
error: errorToThrow,
}));
__classPrivateFieldGet(this, _Conn_closedResolver, "f").resolve();
__classPrivateFieldGet(this, _Conn_closeLock, "f").release();
__classPrivateFieldGet(this, _Conn_callEvent, "f").dispose();
__classPrivateFieldGet(this, _Conn_replyCallEvent, "f").dispose();
__classPrivateFieldGet(this, _Conn_disconnectedEvent, "f").dispose();
__classPrivateFieldGet(this, _Conn_downstreamReplyCallTransformStreamMap, "f").clear();
}
};
/** エンコーディング名のデフォルト値です。 */
Conn.DEFAULT_ENCODING_NAME = transport_1.ENCODING_NAME.PROTOBUF;
/** Ping間隔のデフォルト値です(秒)。 */
Conn.DEFAULT_PING_INTERVAL = 10;
/** Pingタイムアウトのデフォルト値です(秒)。 */
Conn.DEFAULT_PING_TIMEOUT = 1;
/** 有効期限のデフォルト値です(秒)。 */
Conn.DEFAULT_EXPIRY_INTERVAL = 1;
/** Ack返却間隔のデフォルト値です(秒)。 */
Conn.DEFAULT_ACK_INTERVAL = 1;
/** QoSのデフォルト値です。 */
Conn.DEFAULT_QOS = common_1.QOS.UNRELIABLE;
/** 空チャンク省略フラグのデフォルト値です。 */
Conn.DEFAULT_OMIT_EMPTY_CHUNK = false;
/** 永続化するかどうかのデフォルト値です。 */
Conn.DEFAULT_PERSIST = false;
/** クローズのタイムアウトのデフォルト値です(秒)。 */
Conn.DEFAULT_CLOSE_TIMEOUT = 1;
/** アップストリームクローズ時にセッションをクローズするかどうかのデフォルト値です。 */
Conn.DEFAULT_CLOSE_SESSION = false;
/** 自動で再接続するかのデフォルト値です。 */
Conn.DEFAULT_AUTO_RECONNECT = true;
/** 自動で再接続する際の、リトライ間隔の初期値のデフォルト値です(秒)。 */
Conn.DEFAULT_RECONNECT_BASE_INTERVAL = 0.1;
/** 自動で再接続する際の、リトライ間隔のデフォルト値です(秒)。 */
Conn.DEFAULT_RECONNECT_MAX_INTERVAL = 5;
/** 基準時刻を送信する際に永続化するかどうかのデフォルト値です。 */
Conn.DEFAULT_SEND_BASE_TIME_OPTIONS_PERSIST = false;
/**
* @event イベント
*/
Conn.EVENT = {
/**
* E2Eコールを受信した時に呼び出されるイベントです。
*/
CALL: 'call',
/**
* E2Eリプライコールを受信した時に呼び出されるイベントです。
*/
REPLY_CALL: 'replyCall',
/**
* iSCPが切断された時に呼び出されるイベントです。
*/
DISCONNECTED: 'disconnected',
/**
* iSCPの再接続が開始された時に呼び出されるイベントです。
*/
RECONNECTING: 'reconnecting',
/**
* iSCPの再接続が成功した時に呼び出されるイベントです。
*/
RECONNECTED: 'reconnected',
};
//
// Static Classes
//
/**
* Connの中で使用するUpstreamクラス
*/
class InternalUpstream {
constructor(init) {
this.chunkAckWriter = init.chunkAckWriter;
this.reopenWriter = init.reopenWriter;
this.close = init.close;
}
async dispose() {
await this.chunkAckWriter.close();
await this.reopenWriter.close();
await this.close();
}
}
/**
* Connの中で使用するDownstreamクラス
*/
class InternalDownstream {
constructor(init) {
this.chunkWriter = init.chunkWriter;
this.chunkAckCompleteWriter = init.chunkAckCompleteWriter;
this.metadataWriter = init.metadataWriter;
this.reopenWriter = init.reopenWriter;
this.close = init.close;
}
async dispose() {
await this.chunkWriter.close();
await this.chunkAckCompleteWriter.close();
await this.metadataWriter.close();
await this.reopenWriter.close();
await this.close();
}
}
//
// Static functions
//
const toEncodingByName = (encodingName) => {
switch (encodingName) {
case transport_1.ENCODING_NAME.PROTOBUF:
return new encoding_1.Protobuf();
case transport_1.ENCODING_NAME.JSON:
return new encoding_1.Json();
default:
throw new exceptions_1.ISCPUnexpectedError('Unrecognized encoding.');
}
};
const asWireConfig = (wireConfig) => {
if (wireConfig) {
return wireConfig;
}
throw new Error('invalid wireConfig.');
};
const asWire = (wire) => {
if (wire) {
return wire;
}
throw new Error('invalid wire.');
};
//# sourceMappingURL=conn.js.map