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.

217 lines (216 loc) 9.74 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WsClient = void 0; const json_bigint_1 = __importDefault(require("json-bigint")); const wsConnectorPool_1 = require("./wsConnectorPool"); const wsError_1 = require("../common/wsError"); const wsResponse_1 = require("./wsResponse"); const reqid_1 = require("../common/reqid"); const log_1 = __importDefault(require("../common/log")); const utils_1 = require("../common/utils"); const websocket_1 = require("websocket"); class WsClient { constructor(url, timeout) { this.checkURL(url); this._url = url; this._timeout = timeout; } async connect(database) { let _db = this._url.pathname.split('/')[3]; if (database) { _db = database; } let connMsg = { action: 'conn', args: { req_id: reqid_1.ReqId.getReqID(), user: (0, utils_1.safeDecodeURIComponent)(this._url.username), password: (0, utils_1.safeDecodeURIComponent)(this._url.password), db: _db, }, }; this._wsConnector = await wsConnectorPool_1.WebSocketConnectionPool.instance().getConnection(this._url, this._timeout); if (this._wsConnector.readyState() === websocket_1.w3cwebsocket.OPEN) { return; } try { await this._wsConnector.ready(); let result = await this._wsConnector.sendMsg(JSON.stringify(connMsg)); if (result.msg.code == 0) { return; } await this.close(); throw (new wsError_1.WebSocketQueryError(result.msg.code, result.msg.message)); } catch (e) { await this.close(); log_1.default.error(`connection creation failed, url: ${this._url}, code:${e.code}, msg:${e.message}`); throw (new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_WEBSOCKET_CONNECTION_FAIL, `connection creation failed, url: ${this._url}, code:${e.code}, msg:${e.message}`)); } } async execNoResp(queryMsg) { log_1.default.debug('[wsQueryInterface.query.queryMsg]===>' + queryMsg); if (this._wsConnector && this._wsConnector.readyState() === websocket_1.w3cwebsocket.OPEN) { await this._wsConnector.sendMsgNoResp(queryMsg); return; } throw (new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_CONNECTION_CLOSED, "invalid websocket connect")); } // need to construct Response. async exec(queryMsg, bSqlQuery = true) { return new Promise((resolve, reject) => { log_1.default.debug('[wsQueryInterface.query.queryMsg]===>' + queryMsg); if (this._wsConnector && this._wsConnector.readyState() === websocket_1.w3cwebsocket.OPEN) { this._wsConnector.sendMsg(queryMsg).then((e) => { if (e.msg.code == 0) { if (bSqlQuery) { resolve(new wsResponse_1.WSQueryResponse(e)); } else { resolve(e); } } else { reject(new wsError_1.WebSocketInterfaceError(e.msg.code, e.msg.message)); } }).catch((e) => { reject(e); }); } else { reject(new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_CONNECTION_CLOSED, "invalid websocket connect")); } }); } // need to construct Response. async sendBinaryMsg(reqId, action, message, bSqlQuery = true, bResultBinary = false) { return new Promise((resolve, reject) => { if (this._wsConnector && this._wsConnector.readyState() === websocket_1.w3cwebsocket.OPEN) { this._wsConnector.sendBinaryMsg(reqId, action, message).then((e) => { if (bResultBinary) { resolve(e); } if (e.msg.code == 0) { if (bSqlQuery) { resolve(new wsResponse_1.WSQueryResponse(e)); } else { resolve(e); } } else { reject(new wsError_1.WebSocketInterfaceError(e.msg.code, e.msg.message)); } }).catch((e) => { reject(e); }); } else { reject(new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_CONNECTION_CLOSED, "invalid websocket connect")); } }); } getState() { if (this._wsConnector) { return this._wsConnector.readyState(); } return -1; } async ready() { try { this._wsConnector = await wsConnectorPool_1.WebSocketConnectionPool.instance().getConnection(this._url, this._timeout); if (this._wsConnector.readyState() !== websocket_1.w3cwebsocket.OPEN) { await this._wsConnector.ready(); } log_1.default.debug("ready status ", this._url, this._wsConnector.readyState()); return; } catch (e) { log_1.default.error(`connection creation failed, url: ${this._url}, code: ${e.code}, message: ${e.message}`); throw (new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_WEBSOCKET_CONNECTION_FAIL, `connection creation failed, url: ${this._url}, code: ${e.code}, message: ${e.message}`)); } } async sendMsg(msg) { return new Promise((resolve, reject) => { log_1.default.debug("[wsQueryInterface.sendMsg]===>" + msg); if (this._wsConnector && this._wsConnector.readyState() === websocket_1.w3cwebsocket.OPEN) { this._wsConnector.sendMsg(msg).then((e) => { resolve(e); }).catch((e) => reject(e)); } else { reject(new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_CONNECTION_CLOSED, "invalid websocket connect")); } }); } async freeResult(res) { let freeResultMsg = { action: 'free_result', args: { req_id: reqid_1.ReqId.getReqID(), id: res.id, }, }; return new Promise((resolve, reject) => { let jsonStr = json_bigint_1.default.stringify(freeResultMsg); log_1.default.debug("[wsQueryInterface.freeResult.freeResultMsg]===>" + jsonStr); if (this._wsConnector && this._wsConnector.readyState() === websocket_1.w3cwebsocket.OPEN) { this._wsConnector.sendMsgNoResp(jsonStr) .then((e) => { resolve(e); }) .catch((e) => reject(e)); } else { reject(new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_CONNECTION_CLOSED, "invalid websocket connect")); } }); } async version() { let versionMsg = { action: 'version', args: { req_id: reqid_1.ReqId.getReqID() }, }; if (this._wsConnector) { try { if (this._wsConnector.readyState() !== websocket_1.w3cwebsocket.OPEN) { await this._wsConnector.ready(); } let result = await this._wsConnector.sendMsg(json_bigint_1.default.stringify(versionMsg)); if (result.msg.code == 0) { return new wsResponse_1.WSVersionResponse(result).version; } throw (new wsError_1.WebSocketInterfaceError(result.msg.code, result.msg.message)); } catch (e) { log_1.default.error(`connection creation failed, url: ${this._url}, code: ${e.code}, message: ${e.message}`); throw (new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_WEBSOCKET_CONNECTION_FAIL, `connection creation failed, url: ${this._url}, code: ${e.code}, message: ${e.message}`)); } } throw (wsError_1.ErrorCode.ERR_CONNECTION_CLOSED, "invalid websocket connect"); } async close() { if (this._wsConnector) { await wsConnectorPool_1.WebSocketConnectionPool.instance().releaseConnection(this._wsConnector); this._wsConnector = undefined; // this._wsConnector.close(); } } checkURL(url) { // Assert is cloud url if (!url.searchParams.has('token')) { if (!(url.username || url.password)) { throw new wsError_1.WebSocketInterfaceError(wsError_1.ErrorCode.ERR_INVALID_AUTHENTICATION, 'invalid url, password or username needed.'); } } } async checkVersion() { let version = await this.version(); let result = (0, utils_1.compareVersions)(version, WsClient._minVersion); if (result < 0) { log_1.default.error(`TDengine version is too low, current version: ${version}, minimum required version: ${WsClient._minVersion}`); throw (new wsError_1.WebSocketQueryError(wsError_1.ErrorCode.ERR_TDENIGNE_VERSION_IS_TOO_LOW, `Version mismatch. The minimum required TDengine version is ${WsClient._minVersion}`)); } } } exports.WsClient = WsClient; WsClient._minVersion = "3.3.2.0";