@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
JavaScript
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');
;