UNPKG

@tdengine/websocket

Version:

The websocket Node.js connector for TDengine. TDengine versions 3.3.2.0 and above are recommended to use this connector.

126 lines (125 loc) 5.58 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebSocketConnectionPool = void 0; const async_mutex_1 = require("async-mutex"); const wsConnector_1 = require("./wsConnector"); const wsError_1 = require("../common/wsError"); const log_1 = __importDefault(require("../common/log")); const websocket_1 = require("websocket"); const mutex = new async_mutex_1.Mutex(); class WebSocketConnectionPool { constructor(maxConnections = -1) { this.pool = new Map(); this._maxConnections = maxConnections; WebSocketConnectionPool.sharedBuffer = new SharedArrayBuffer(4); WebSocketConnectionPool.sharedArray = new Int32Array(WebSocketConnectionPool.sharedBuffer); Atomics.store(WebSocketConnectionPool.sharedArray, 0, 0); } static instance(maxConnections = -1) { if (!WebSocketConnectionPool._instance) { WebSocketConnectionPool._instance = new WebSocketConnectionPool(maxConnections); } return WebSocketConnectionPool._instance; } async getConnection(url, timeout) { let connectAddr = url.origin.concat(url.pathname).concat(url.search); let connector; const unlock = await mutex.acquire(); try { if (this.pool.has(connectAddr)) { const connectors = this.pool.get(connectAddr); while (connectors && connectors.length > 0) { const candidate = connectors.pop(); if (!candidate) { continue; } if (candidate && candidate.readyState() === websocket_1.w3cwebsocket.OPEN) { connector = candidate; break; } else if (candidate) { Atomics.add(WebSocketConnectionPool.sharedArray, 0, -1); candidate.close(); log_1.default.error(`getConnection, current connection status fail, url: ${connectAddr}`); } } } if (connector) { log_1.default.debug("get connection success:" + Atomics.load(WebSocketConnectionPool.sharedArray, 0)); return connector; } if (this._maxConnections != -1 && Atomics.load(WebSocketConnectionPool.sharedArray, 0) > this._maxConnections) { throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_WEBSOCKET_CONNECTION_ARRIVED_LIMIT, "websocket connect arrived limited:" + Atomics.load(WebSocketConnectionPool.sharedArray, 0)); } Atomics.add(WebSocketConnectionPool.sharedArray, 0, 1); log_1.default.info("getConnection, new connection count:" + Atomics.load(WebSocketConnectionPool.sharedArray, 0) + ", connectAddr:" + connectAddr); return new wsConnector_1.WebSocketConnector(url, timeout); } finally { unlock(); } } async releaseConnection(connector) { if (connector) { const unlock = await mutex.acquire(); try { if (connector.readyState() === websocket_1.w3cwebsocket.OPEN) { let url = connector.getWsURL(); let connectAddr = url.origin.concat(url.pathname).concat(url.search); let connectors = this.pool.get(connectAddr); if (!connectors) { connectors = new Array(); connectors.push(connector); this.pool.set(connectAddr, connectors); } else { connectors.push(connector); } log_1.default.info("releaseConnection, current connection count:" + connectors.length); } else { Atomics.add(WebSocketConnectionPool.sharedArray, 0, -1); connector.close(); log_1.default.info("releaseConnection, current connection status fail:" + Atomics.load(WebSocketConnectionPool.sharedArray, 0)); } } finally { unlock(); } } } destroyed() { let num = 0; if (this.pool) { for (let values of this.pool.values()) { for (let i in values) { num++; values[i].close(); } } } log_1.default.info("destroyed connect:" + Atomics.load(WebSocketConnectionPool.sharedArray, 0) + " current count:" + num); Atomics.store(WebSocketConnectionPool.sharedArray, 0, 0); this.pool = new Map(); } } exports.WebSocketConnectionPool = WebSocketConnectionPool; process.on('exit', (code) => { log_1.default.info("begin destroy connect"); WebSocketConnectionPool.instance().destroyed(); process.exit(); }); process.on('SIGINT', () => { log_1.default.info('Received SIGINT. Press Control-D to exit, begin destroy connect...'); WebSocketConnectionPool.instance().destroyed(); process.exit(); }); process.on('SIGTERM', () => { log_1.default.info('Received SIGINT. Press Control-D to exit, begin destroy connect'); WebSocketConnectionPool.instance().destroyed(); process.exit(); }); // process.kill(process.pid, 'SIGINT');