UNPKG

@liskhq/lisk-api-client

Version:
115 lines 4.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IPCChannel = void 0; const path = require("path"); const os_1 = require("os"); const events_1 = require("events"); const zeromq_1 = require("zeromq"); const utils_1 = require("./utils"); const CONNECTION_TIMEOUT = 5000; const RESPONSE_TIMEOUT = 10000; const getSocketsPath = (dataPath) => { const socketDir = path.join(path.resolve(dataPath.replace('~', (0, os_1.homedir)())), 'tmp', 'sockets'); return { pub: `ipc://${socketDir}/external.pub.ipc`, sub: `ipc://${socketDir}/external.sub.ipc`, rpc: `ipc://${socketDir}/engine.external.rpc.ipc`, }; }; class IPCChannel { constructor(dataPath) { this.isAlive = false; this._pendingRequests = {}; const socketsDir = getSocketsPath(dataPath); this._eventPubSocketPath = socketsDir.pub; this._rpcServerSocketPath = socketsDir.rpc; this._subSocket = new zeromq_1.Subscriber(); this._rpcClient = new zeromq_1.Dealer(); this._events = new events_1.EventEmitter(); this._id = 0; } async connect() { try { await new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error('IPC Socket client connection timeout. Please check if IPC server is running.')); }, CONNECTION_TIMEOUT); this._subSocket.events.on('connect', () => { clearTimeout(timeout); resolve(); }); this._subSocket.events.on('bind:error', reject); this._subSocket.connect(this._eventPubSocketPath); }); await new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error('IPC Socket client connection timeout. Please check if IPC server is running.')); }, CONNECTION_TIMEOUT); this._rpcClient.events.on('connect', () => { clearTimeout(timeout); resolve(undefined); }); this._rpcClient.events.on('bind:error', reject); this._rpcClient.connect(this._rpcServerSocketPath); }); this.isAlive = true; } catch (error) { this._subSocket.close(); this._rpcClient.close(); throw error; } this._listenToRPCResponse().catch(() => { }); this._listenToEvents().catch(() => { }); } async disconnect() { this._subSocket.close(); this._rpcClient.close(); this.isAlive = false; } async invoke(actionName, params) { this._id += 1; const action = { id: this._id, jsonrpc: '2.0', method: actionName, params: params !== null && params !== void 0 ? params : {}, }; await this._rpcClient.send([JSON.stringify(action)]); const response = (0, utils_1.defer)(); this._pendingRequests[action.id] = response; return (0, utils_1.promiseWithTimeout)([response.promise], RESPONSE_TIMEOUT, `Response not received in ${RESPONSE_TIMEOUT}ms`); } subscribe(eventName, cb) { this._subSocket.subscribe(eventName); this._events.on(eventName, cb); } unsubscribe(eventName, cb) { this._subSocket.unsubscribe(eventName); this._events.off(eventName, cb); } async _listenToRPCResponse() { for await (const [eventData] of this._rpcClient) { const res = JSON.parse(eventData.toString()); const id = typeof res.id === 'number' ? res.id : parseInt(res.id, 10); if (this._pendingRequests[id]) { if (res.error) { this._pendingRequests[id].reject((0, utils_1.convertRPCError)(res.error)); } else { this._pendingRequests[id].resolve(res.result); } delete this._pendingRequests[id]; } } } async _listenToEvents() { this._subSocket.subscribe('invoke'); for await (const [_event, eventData] of this._subSocket) { const res = JSON.parse(eventData.toString()); this._events.emit(res.method, res.params); } } } exports.IPCChannel = IPCChannel; //# sourceMappingURL=ipc_channel.js.map