@tdengine/websocket 3.2.3 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/package.json +1 -1
- package/lib/src/client/wsClient.d.ts +23 -7
- package/lib/src/client/wsClient.d.ts.map +1 -1
- package/lib/src/client/wsClient.js +154 -139
- package/lib/src/client/wsConnector.d.ts +55 -9
- package/lib/src/client/wsConnector.d.ts.map +1 -1
- package/lib/src/client/wsConnector.js +519 -100
- package/lib/src/client/wsConnectorPool.d.ts +5 -1
- package/lib/src/client/wsConnectorPool.d.ts.map +1 -1
- package/lib/src/client/wsConnectorPool.js +61 -43
- package/lib/src/client/wsEventCallback.d.ts +3 -0
- package/lib/src/client/wsEventCallback.d.ts.map +1 -1
- package/lib/src/client/wsEventCallback.js +67 -8
- package/lib/src/common/addressConnectionTracker.d.ts +11 -0
- package/lib/src/common/addressConnectionTracker.d.ts.map +1 -0
- package/lib/src/common/addressConnectionTracker.js +53 -0
- package/lib/src/common/dsn.d.ts +14 -2
- package/lib/src/common/dsn.d.ts.map +1 -1
- package/lib/src/common/dsn.js +91 -22
- package/lib/src/common/taosResult.d.ts.map +1 -1
- package/lib/src/common/taosResult.js +0 -5
- package/lib/src/common/urlParser.d.ts +32 -0
- package/lib/src/common/urlParser.d.ts.map +1 -0
- package/lib/src/common/urlParser.js +201 -0
- package/lib/src/common/utils.d.ts +2 -1
- package/lib/src/common/utils.d.ts.map +1 -1
- package/lib/src/common/utils.js +35 -34
- package/lib/src/sql/wsSql.js +2 -2
- package/lib/src/stmt/FieldBindParams.d.ts.map +1 -1
- package/lib/src/stmt/wsColumnInfo.d.ts.map +1 -1
- package/lib/src/stmt/wsParams1.d.ts.map +1 -1
- package/lib/src/stmt/wsParams1.js +26 -26
- package/lib/src/stmt/wsParams2.d.ts.map +1 -1
- package/lib/src/stmt/wsParams2.js +0 -3
- package/lib/src/stmt/wsParamsBase.d.ts.map +1 -1
- package/lib/src/stmt/wsProto.d.ts.map +1 -1
- package/lib/src/stmt/wsProto.js +16 -16
- package/lib/src/stmt/wsStmt1.d.ts.map +1 -1
- package/lib/src/stmt/wsStmt2.d.ts +12 -4
- package/lib/src/stmt/wsStmt2.d.ts.map +1 -1
- package/lib/src/stmt/wsStmt2.js +182 -64
- package/lib/src/stmt/wsTableInfo.d.ts.map +1 -1
- package/lib/src/tmq/config.d.ts +3 -2
- package/lib/src/tmq/config.d.ts.map +1 -1
- package/lib/src/tmq/config.js +15 -15
- package/lib/src/tmq/wsTmq.d.ts +4 -1
- package/lib/src/tmq/wsTmq.d.ts.map +1 -1
- package/lib/src/tmq/wsTmq.js +50 -27
- package/lib/test/bulkPulling/a.test.d.ts +2 -0
- package/lib/test/bulkPulling/a.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/a.test.js +166 -0
- package/lib/test/bulkPulling/dsn.test.js +19 -0
- package/lib/test/bulkPulling/retryConfig.test.js +11 -11
- package/lib/test/bulkPulling/sql.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/sql.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/sql.failover.test.js +338 -0
- package/lib/test/bulkPulling/stmt2.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/stmt2.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/stmt2.failover.test.js +313 -0
- package/lib/test/bulkPulling/stmt2.init.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/stmt2.init.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/stmt2.init.failover.test.js +50 -0
- package/lib/test/bulkPulling/tmq.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/tmq.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/tmq.failover.test.js +404 -0
- package/lib/test/bulkPulling/urlParser.test.d.ts +2 -0
- package/lib/test/bulkPulling/urlParser.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/urlParser.test.js +452 -0
- package/lib/test/bulkPulling/wsClient.reconnect.integration.test.js +2 -2
- package/lib/test/bulkPulling/wsClient.recovery.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsClient.recovery.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsClient.recovery.test.js +104 -0
- package/lib/test/bulkPulling/wsConfig.dsn.test.js +2 -0
- package/lib/test/bulkPulling/wsConnector.failover.test.js +396 -27
- package/lib/test/bulkPulling/wsConnectorPool.key.test.js +12 -10
- package/lib/test/bulkPulling/wsConnectorPool.keyAuth.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsConnectorPool.keyAuth.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsConnectorPool.keyAuth.test.js +28 -0
- package/lib/test/bulkPulling/wsProxy.failover.integration.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsProxy.failover.integration.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsProxy.failover.integration.test.js +120 -0
- package/lib/test/bulkPulling/wsProxy.failover.test.d.ts +2 -0
- package/lib/test/bulkPulling/wsProxy.failover.test.d.ts.map +1 -0
- package/lib/test/bulkPulling/wsProxy.failover.test.js +465 -0
- package/lib/test/client/wsClient.recovery.test.d.ts +2 -0
- package/lib/test/client/wsClient.recovery.test.d.ts.map +1 -0
- package/lib/test/client/wsClient.recovery.test.js +122 -0
- package/lib/test/client/wsConnectPool.test.d.ts +2 -0
- package/lib/test/client/wsConnectPool.test.d.ts.map +1 -0
- package/lib/test/client/wsConnectPool.test.js +147 -0
- package/lib/test/client/wsConnector.failover.test.d.ts +2 -0
- package/lib/test/client/wsConnector.failover.test.d.ts.map +1 -0
- package/lib/test/client/wsConnector.failover.test.js +681 -0
- package/lib/test/client/wsConnector.leastConnections.test.d.ts +2 -0
- package/lib/test/client/wsConnector.leastConnections.test.d.ts.map +1 -0
- package/lib/test/client/wsConnector.leastConnections.test.js +71 -0
- package/lib/test/client/wsConnectorPool.key.test.d.ts +2 -0
- package/lib/test/client/wsConnectorPool.key.test.d.ts.map +1 -0
- package/lib/test/client/wsConnectorPool.key.test.js +127 -0
- package/lib/test/client/wsEventCallback.test.d.ts +2 -0
- package/lib/test/client/wsEventCallback.test.d.ts.map +1 -0
- package/lib/test/client/wsEventCallback.test.js +98 -0
- package/lib/test/common/addressConnectionTracker.test.d.ts +2 -0
- package/lib/test/common/addressConnectionTracker.test.d.ts.map +1 -0
- package/lib/test/common/addressConnectionTracker.test.js +74 -0
- package/lib/test/common/dsn.test.d.ts +2 -0
- package/lib/test/common/dsn.test.d.ts.map +1 -0
- package/lib/test/common/dsn.test.js +406 -0
- package/lib/test/common/log.test.d.ts +2 -0
- package/lib/test/common/log.test.d.ts.map +1 -0
- package/lib/test/common/log.test.js +54 -0
- package/lib/test/common/utils.test.d.ts +2 -0
- package/lib/test/common/utils.test.d.ts.map +1 -0
- package/lib/test/common/utils.test.js +13 -0
- package/lib/test/common/wsConfig.dsn.test.d.ts +2 -0
- package/lib/test/common/wsConfig.dsn.test.d.ts.map +1 -0
- package/lib/test/common/wsConfig.dsn.test.js +39 -0
- package/lib/test/helpers/utils.d.ts +27 -0
- package/lib/test/helpers/utils.d.ts.map +1 -0
- package/lib/test/helpers/utils.js +341 -0
- package/lib/test/helpers/wsFailoverProxy.d.ts +109 -0
- package/lib/test/helpers/wsFailoverProxy.d.ts.map +1 -0
- package/lib/test/helpers/wsFailoverProxy.js +420 -0
- package/lib/test/helpers/wsProxy.d.ts +110 -0
- package/lib/test/helpers/wsProxy.d.ts.map +1 -0
- package/lib/test/helpers/wsProxy.js +429 -0
- package/lib/test/sql/core/decimal.test.d.ts +2 -0
- package/lib/test/sql/core/decimal.test.d.ts.map +1 -0
- package/lib/test/sql/core/decimal.test.js +153 -0
- package/lib/test/sql/core/queryTables.test.d.ts +2 -0
- package/lib/test/sql/core/queryTables.test.d.ts.map +1 -0
- package/lib/test/sql/core/queryTables.test.js +506 -0
- package/lib/test/sql/core/schemaless.test.d.ts +2 -0
- package/lib/test/sql/core/schemaless.test.d.ts.map +1 -0
- package/lib/test/sql/core/schemaless.test.js +102 -0
- package/lib/test/sql/core/sql.test.d.ts +2 -0
- package/lib/test/sql/core/sql.test.d.ts.map +1 -0
- package/lib/test/sql/core/sql.test.js +324 -0
- package/lib/test/sql/decimal.test.d.ts +2 -0
- package/lib/test/sql/decimal.test.d.ts.map +1 -0
- package/lib/test/sql/decimal.test.js +153 -0
- package/lib/test/sql/failover/sql.failover.test.d.ts +2 -0
- package/lib/test/sql/failover/sql.failover.test.d.ts.map +1 -0
- package/lib/test/sql/failover/sql.failover.test.js +341 -0
- package/lib/test/sql/queryTables.test.d.ts +2 -0
- package/lib/test/sql/queryTables.test.d.ts.map +1 -0
- package/lib/test/sql/queryTables.test.js +506 -0
- package/lib/test/sql/schemaless.test.d.ts +2 -0
- package/lib/test/sql/schemaless.test.d.ts.map +1 -0
- package/lib/test/sql/schemaless.test.js +102 -0
- package/lib/test/sql/sql.failover.test.d.ts +2 -0
- package/lib/test/sql/sql.failover.test.d.ts.map +1 -0
- package/lib/test/sql/sql.failover.test.js +341 -0
- package/lib/test/sql/sql.test.d.ts +2 -0
- package/lib/test/sql/sql.test.d.ts.map +1 -0
- package/lib/test/sql/sql.test.js +324 -0
- package/lib/test/stmt/failover/stmt2.failover.mock.test.d.ts +2 -0
- package/lib/test/stmt/failover/stmt2.failover.mock.test.d.ts.map +1 -0
- package/lib/test/stmt/failover/stmt2.failover.mock.test.js +341 -0
- package/lib/test/stmt/failover/stmt2.failover.test.d.ts +2 -0
- package/lib/test/stmt/failover/stmt2.failover.test.d.ts.map +1 -0
- package/lib/test/stmt/failover/stmt2.failover.test.js +384 -0
- package/lib/test/stmt/stmt1.func.test.d.ts +2 -0
- package/lib/test/stmt/stmt1.func.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt1.func.test.js +418 -0
- package/lib/test/stmt/stmt1.type.test.d.ts +2 -0
- package/lib/test/stmt/stmt1.type.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt1.type.test.js +399 -0
- package/lib/test/stmt/stmt2.failover.mock.test.d.ts +2 -0
- package/lib/test/stmt/stmt2.failover.mock.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt2.failover.mock.test.js +341 -0
- package/lib/test/stmt/stmt2.failover.test.d.ts +2 -0
- package/lib/test/stmt/stmt2.failover.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt2.failover.test.js +384 -0
- package/lib/test/stmt/stmt2.func.test.d.ts +2 -0
- package/lib/test/stmt/stmt2.func.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt2.func.test.js +537 -0
- package/lib/test/stmt/stmt2.type.test.d.ts +2 -0
- package/lib/test/stmt/stmt2.type.test.d.ts.map +1 -0
- package/lib/test/stmt/stmt2.type.test.js +401 -0
- package/lib/test/stmt/v1/stmt1.func.test.d.ts +2 -0
- package/lib/test/stmt/v1/stmt1.func.test.d.ts.map +1 -0
- package/lib/test/stmt/v1/stmt1.func.test.js +418 -0
- package/lib/test/stmt/v1/stmt1.type.test.d.ts +2 -0
- package/lib/test/stmt/v1/stmt1.type.test.d.ts.map +1 -0
- package/lib/test/stmt/v1/stmt1.type.test.js +399 -0
- package/lib/test/stmt/v2/stmt2.func.test.d.ts +2 -0
- package/lib/test/stmt/v2/stmt2.func.test.d.ts.map +1 -0
- package/lib/test/stmt/v2/stmt2.func.test.js +537 -0
- package/lib/test/stmt/v2/stmt2.type.test.d.ts +2 -0
- package/lib/test/stmt/v2/stmt2.type.test.d.ts.map +1 -0
- package/lib/test/stmt/v2/stmt2.type.test.js +401 -0
- package/lib/test/tmq/cloud/cloud.tmq.test.d.ts +2 -0
- package/lib/test/tmq/cloud/cloud.tmq.test.d.ts.map +1 -0
- package/lib/test/tmq/cloud/cloud.tmq.test.js +84 -0
- package/lib/test/tmq/cloud/tmq.cloud.test.d.ts +2 -0
- package/lib/test/tmq/cloud/tmq.cloud.test.d.ts.map +1 -0
- package/lib/test/tmq/cloud/tmq.cloud.test.js +82 -0
- package/lib/test/tmq/core/tmq.config.test.d.ts +2 -0
- package/lib/test/tmq/core/tmq.config.test.d.ts.map +1 -0
- package/lib/test/tmq/core/tmq.config.test.js +83 -0
- package/lib/test/tmq/core/tmq.test.d.ts +2 -0
- package/lib/test/tmq/core/tmq.test.d.ts.map +1 -0
- package/lib/test/tmq/core/tmq.test.js +513 -0
- package/lib/test/tmq/failover/tmq.failover.test.d.ts +2 -0
- package/lib/test/tmq/failover/tmq.failover.test.d.ts.map +1 -0
- package/lib/test/tmq/failover/tmq.failover.test.js +404 -0
- package/lib/test/tmq/tmq.cloud.test.d.ts +2 -0
- package/lib/test/tmq/tmq.cloud.test.d.ts.map +1 -0
- package/lib/test/tmq/tmq.cloud.test.js +82 -0
- package/lib/test/tmq/tmq.config.test.d.ts +2 -0
- package/lib/test/tmq/tmq.config.test.d.ts.map +1 -0
- package/lib/test/tmq/tmq.config.test.js +94 -0
- package/lib/test/tmq/tmq.failover.test.d.ts +2 -0
- package/lib/test/tmq/tmq.failover.test.d.ts.map +1 -0
- package/lib/test/tmq/tmq.failover.test.js +404 -0
- package/lib/test/tmq/tmq.test.d.ts +2 -0
- package/lib/test/tmq/tmq.test.d.ts.map +1 -0
- package/lib/test/tmq/tmq.test.js +513 -0
- package/lib/test/unit/connectionManager.test.d.ts +2 -0
- package/lib/test/unit/connectionManager.test.d.ts.map +1 -0
- package/lib/test/unit/connectionManager.test.js +91 -0
- package/package.json +1 -1
- package/readme.md +2 -2
|
@@ -3,60 +3,193 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.WebSocketConnector = void 0;
|
|
6
|
+
exports.WebSocketConnector = exports.RetryConfig = void 0;
|
|
7
7
|
const websocket_1 = require("websocket");
|
|
8
|
+
const addressConnectionTracker_1 = require("../common/addressConnectionTracker");
|
|
8
9
|
const wsError_1 = require("../common/wsError");
|
|
9
10
|
const wsEventCallback_1 = require("./wsEventCallback");
|
|
10
11
|
const log_1 = __importDefault(require("../common/log"));
|
|
11
|
-
const reqid_1 = require("../common/reqid");
|
|
12
12
|
const utils_1 = require("../common/utils");
|
|
13
|
-
class
|
|
14
|
-
constructor(
|
|
15
|
-
this.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
log_1.default.error(`webSocket connection failed, url: ${(0, utils_1.maskUrlForLog)(new URL(this.url))}, error: ${err.message}`);
|
|
30
|
-
};
|
|
31
|
-
this._wsConn.onclose = this._onclose;
|
|
32
|
-
this._wsConn.onmessage = this._onmessage;
|
|
33
|
-
this._wsConn._binaryType = "arraybuffer";
|
|
13
|
+
class InflightRequestStore {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.nextMsgId = 1n;
|
|
16
|
+
this.reqIdToMsgId = new Map();
|
|
17
|
+
this.msgIdToRequest = new Map();
|
|
18
|
+
}
|
|
19
|
+
insert(req) {
|
|
20
|
+
const msgId = this.nextMsgId;
|
|
21
|
+
this.nextMsgId += 1n;
|
|
22
|
+
this.reqIdToMsgId.set(req.reqId, msgId);
|
|
23
|
+
this.msgIdToRequest.set(msgId, req);
|
|
24
|
+
}
|
|
25
|
+
remove(reqId) {
|
|
26
|
+
const msgId = this.reqIdToMsgId.get(reqId);
|
|
27
|
+
if (msgId === undefined) {
|
|
28
|
+
return;
|
|
34
29
|
}
|
|
35
|
-
|
|
30
|
+
this.reqIdToMsgId.delete(reqId);
|
|
31
|
+
this.msgIdToRequest.delete(msgId);
|
|
32
|
+
}
|
|
33
|
+
getRequests() {
|
|
34
|
+
return Array.from(this.msgIdToRequest.entries())
|
|
35
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
36
|
+
.map(([, req]) => req);
|
|
37
|
+
}
|
|
38
|
+
clear() {
|
|
39
|
+
this.nextMsgId = 1n;
|
|
40
|
+
this.reqIdToMsgId.clear();
|
|
41
|
+
this.msgIdToRequest.clear();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const RETRIABLE_ACTIONS = new Set(["insert", "options_connection", "poll", "subscribe"]);
|
|
45
|
+
// TDengine websocket binary op codes that are safe to replay after reconnect.
|
|
46
|
+
const BINARY_RETRIABLE_ACTIONS = new Set([4n, 5n, 6n, 10n]);
|
|
47
|
+
const DEFAULT_RETRIES = 5;
|
|
48
|
+
const DEFAULT_BACKOFF_MS = 200;
|
|
49
|
+
const DEFAULT_BACKOFF_MAX_MS = 2000;
|
|
50
|
+
const NETWORK_ERROR_CODES = new Set([
|
|
51
|
+
"econnreset",
|
|
52
|
+
"econnrefused",
|
|
53
|
+
"ehostunreach",
|
|
54
|
+
"enotfound",
|
|
55
|
+
"eai_again",
|
|
56
|
+
"epipe",
|
|
57
|
+
"etimedout",
|
|
58
|
+
"err_socket_closed",
|
|
59
|
+
"err_stream_write_after_end",
|
|
60
|
+
]);
|
|
61
|
+
const NETWORK_ERROR_MESSAGE_PATTERNS = [
|
|
62
|
+
"not connected",
|
|
63
|
+
"socket",
|
|
64
|
+
"network",
|
|
65
|
+
"econnreset",
|
|
66
|
+
"econnrefused",
|
|
67
|
+
"epipe",
|
|
68
|
+
"etimedout",
|
|
69
|
+
"write after end",
|
|
70
|
+
"broken pipe",
|
|
71
|
+
"connection reset",
|
|
72
|
+
"connection closed",
|
|
73
|
+
];
|
|
74
|
+
function parseNonNegativeInt(value, fallback) {
|
|
75
|
+
return parseIntWithValidation(value, fallback, (parsed) => parsed >= 0);
|
|
76
|
+
}
|
|
77
|
+
function parsePositiveInt(value, fallback) {
|
|
78
|
+
return parseIntWithValidation(value, fallback, (parsed) => parsed > 0);
|
|
79
|
+
}
|
|
80
|
+
function parseIntWithValidation(value, fallback, isValid) {
|
|
81
|
+
if (value === undefined || value === null || value.length === 0) {
|
|
82
|
+
return fallback;
|
|
83
|
+
}
|
|
84
|
+
const parsed = Number.parseInt(value, 10);
|
|
85
|
+
if (Number.isNaN(parsed) || !isValid(parsed)) {
|
|
86
|
+
return fallback;
|
|
87
|
+
}
|
|
88
|
+
return parsed;
|
|
89
|
+
}
|
|
90
|
+
class RetryConfig {
|
|
91
|
+
constructor(retries, retryBackoffMs, retryBackoffMaxMs) {
|
|
92
|
+
this.retries = retries;
|
|
93
|
+
this.retryBackoffMs = retryBackoffMs;
|
|
94
|
+
this.retryBackoffMaxMs = Math.max(retryBackoffMs, retryBackoffMaxMs);
|
|
95
|
+
}
|
|
96
|
+
getBackoffDelay(attempt) {
|
|
97
|
+
const safeAttempt = Math.max(0, attempt);
|
|
98
|
+
const rawDelay = this.retryBackoffMs * Math.pow(2, safeAttempt);
|
|
99
|
+
const finiteDelay = Number.isFinite(rawDelay) ? rawDelay : this.retryBackoffMaxMs;
|
|
100
|
+
return Math.min(finiteDelay, this.retryBackoffMaxMs);
|
|
101
|
+
}
|
|
102
|
+
static fromDsn(dsn) {
|
|
103
|
+
const retries = parseNonNegativeInt(dsn.params.get("retries"), DEFAULT_RETRIES);
|
|
104
|
+
const retryBackoffMs = parsePositiveInt(dsn.params.get("retry_backoff_ms"), DEFAULT_BACKOFF_MS);
|
|
105
|
+
const retryBackoffMaxMs = parsePositiveInt(dsn.params.get("retry_backoff_max_ms"), DEFAULT_BACKOFF_MAX_MS);
|
|
106
|
+
return new RetryConfig(retries, retryBackoffMs, retryBackoffMaxMs);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.RetryConfig = RetryConfig;
|
|
110
|
+
class WebSocketConnector {
|
|
111
|
+
constructor(dsn, poolKey, timeout) {
|
|
112
|
+
this._suppressedSockets = new WeakSet();
|
|
113
|
+
this._reconnectLock = null;
|
|
114
|
+
this._isReconnecting = false;
|
|
115
|
+
this._allowReconnect = true;
|
|
116
|
+
this._connectionReady = Promise.resolve();
|
|
117
|
+
this._sessionRecoveryHook = null;
|
|
118
|
+
this._timeout = 60000;
|
|
119
|
+
if (!dsn || dsn.addresses.length === 0) {
|
|
36
120
|
throw new wsError_1.WebSocketQueryError(wsError_1.ErrorCode.ERR_INVALID_URL, "websocket URL must be defined");
|
|
37
121
|
}
|
|
122
|
+
this._poolKey = poolKey;
|
|
123
|
+
this._dsn = dsn;
|
|
124
|
+
this._currentAddress = this.selectLeastConnectedAddress();
|
|
125
|
+
this._retryConfig = RetryConfig.fromDsn(dsn);
|
|
126
|
+
this._inflightStore = new InflightRequestStore();
|
|
127
|
+
if (timeout) {
|
|
128
|
+
this._timeout = timeout;
|
|
129
|
+
}
|
|
130
|
+
log_1.default.info(`Initial websocket address selected: ${this.getCurrentAddress()}`);
|
|
131
|
+
this.createConnection();
|
|
38
132
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
133
|
+
refreshRetryConfig(dsn) {
|
|
134
|
+
this._retryConfig = RetryConfig.fromDsn(dsn);
|
|
135
|
+
}
|
|
136
|
+
buildUrl(addr) {
|
|
137
|
+
const path = this._dsn.path();
|
|
138
|
+
const url = new URL(`${this._dsn.scheme}://${addr.host}:${addr.port}/${path}`);
|
|
139
|
+
const forwardedParams = ["token", "bearer_token"];
|
|
140
|
+
for (const key of forwardedParams) {
|
|
141
|
+
const value = this._dsn.params.get(key);
|
|
142
|
+
if (value !== undefined) {
|
|
143
|
+
url.searchParams.set(key, value);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return url.toString();
|
|
147
|
+
}
|
|
148
|
+
createConnection() {
|
|
149
|
+
const conn = new websocket_1.w3cwebsocket(this.buildUrl(this._currentAddress), undefined, undefined, undefined, undefined, {
|
|
150
|
+
maxReceivedFrameSize: 0x60000000,
|
|
151
|
+
maxReceivedMessageSize: 0x60000000,
|
|
152
|
+
});
|
|
153
|
+
conn._binaryType = "arraybuffer";
|
|
154
|
+
conn.onmessage = this._onmessage;
|
|
155
|
+
this._connectionReady = new Promise((resolve, reject) => {
|
|
156
|
+
let settled = false;
|
|
157
|
+
const settle = (handler) => {
|
|
158
|
+
if (settled) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
settled = true;
|
|
162
|
+
clearTimeout(timeoutId);
|
|
163
|
+
handler();
|
|
164
|
+
};
|
|
165
|
+
const timeoutId = setTimeout(() => {
|
|
166
|
+
settle(() => {
|
|
167
|
+
reject(new wsError_1.WebSocketQueryError(wsError_1.ErrorCode.ERR_WEBSOCKET_QUERY_TIMEOUT, `websocket connection timeout with ${this._timeout} milliseconds`));
|
|
168
|
+
});
|
|
169
|
+
}, this._timeout);
|
|
170
|
+
conn.onopen = () => {
|
|
49
171
|
log_1.default.debug("websocket connection opened");
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
172
|
+
addressConnectionTracker_1.AddressConnectionTracker.instance().increment(this.getCurrentAddress());
|
|
173
|
+
settle(resolve);
|
|
174
|
+
};
|
|
175
|
+
conn.onerror = (err) => {
|
|
176
|
+
log_1.default.error(`webSocket connection failed, url: ${(0, utils_1.maskUrlForLog)(new URL(conn.url))}, error: ${err.message}`);
|
|
177
|
+
if (conn.readyState !== websocket_1.w3cwebsocket.OPEN) {
|
|
178
|
+
settle(() => reject(err));
|
|
179
|
+
}
|
|
180
|
+
void this.handleDisconnect(conn);
|
|
181
|
+
};
|
|
182
|
+
conn.onclose = (e) => {
|
|
183
|
+
log_1.default.info(`websocket connection closed, code: ${e.code}, reason: ${e.reason}`);
|
|
184
|
+
if (conn.readyState !== websocket_1.w3cwebsocket.OPEN) {
|
|
185
|
+
settle(() => {
|
|
186
|
+
reject(new wsError_1.WebSocketQueryError(wsError_1.ErrorCode.ERR_WEBSOCKET_CONNECTION_FAIL, `websocket connection closed: ${e.code} ${e.reason}`));
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
void this.handleDisconnect(conn, e);
|
|
55
190
|
};
|
|
56
191
|
});
|
|
57
|
-
|
|
58
|
-
async _onclose(e) {
|
|
59
|
-
log_1.default.info("websocket connection closed");
|
|
192
|
+
this._conn = conn;
|
|
60
193
|
}
|
|
61
194
|
_onmessage(event) {
|
|
62
195
|
let data = event.data;
|
|
@@ -74,85 +207,371 @@ class WebSocketConnector {
|
|
|
74
207
|
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_INVALID_MESSAGE_TYPE, `invalid message type ${Object.prototype.toString.call(data)}`);
|
|
75
208
|
}
|
|
76
209
|
}
|
|
77
|
-
|
|
78
|
-
if (this.
|
|
79
|
-
|
|
210
|
+
shouldSkipReconnect(conn) {
|
|
211
|
+
if (!this.isReconnectAllowed()) {
|
|
212
|
+
return true;
|
|
80
213
|
}
|
|
81
|
-
|
|
82
|
-
|
|
214
|
+
return this._suppressedSockets.has(conn);
|
|
215
|
+
}
|
|
216
|
+
async failNonRetriableCallbacksOnDisconnect() {
|
|
217
|
+
const keepReqIds = new Set(this._inflightStore.getRequests().map((req) => req.reqId));
|
|
218
|
+
await wsEventCallback_1.WsEventCallback.instance().rejectCallbacksExceptReqIds(keepReqIds, new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_CONNECTION_CLOSED, "websocket connection closed before response was received"), this._poolKey);
|
|
219
|
+
}
|
|
220
|
+
async handleDisconnect(conn, event) {
|
|
221
|
+
if (this.shouldSkipReconnect(conn) || this._isReconnecting) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (event && event.code === 1000) {
|
|
225
|
+
log_1.default.info("Websocket closed normally, skipping reconnect.");
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
await this.failNonRetriableCallbacksOnDisconnect();
|
|
229
|
+
try {
|
|
230
|
+
await this.triggerReconnect();
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
const type = event ? 'close' : 'error';
|
|
234
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
235
|
+
log_1.default.error(`Reconnect failed after websocket ${type}: ${message}`);
|
|
83
236
|
}
|
|
84
237
|
}
|
|
85
|
-
|
|
86
|
-
|
|
238
|
+
extractReqId(reqId) {
|
|
239
|
+
if (reqId === undefined || reqId === null) {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
return BigInt(reqId);
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
87
248
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
249
|
+
isRetriableAction(action) {
|
|
250
|
+
return RETRIABLE_ACTIONS.has(action);
|
|
251
|
+
}
|
|
252
|
+
extractBinaryAction(message) {
|
|
253
|
+
if (message.byteLength < 24) {
|
|
254
|
+
return -1n;
|
|
93
255
|
}
|
|
94
|
-
return new
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
256
|
+
return new DataView(message, 16, 8).getBigInt64(0, true);
|
|
257
|
+
}
|
|
258
|
+
isRetriableBinaryAction(action) {
|
|
259
|
+
return BINARY_RETRIABLE_ACTIONS.has(action);
|
|
260
|
+
}
|
|
261
|
+
isNetworkError(err) {
|
|
262
|
+
if (!this._conn || this._conn.readyState !== websocket_1.w3cwebsocket.OPEN) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
const errObj = err;
|
|
266
|
+
const code = errObj?.code;
|
|
267
|
+
if (typeof code === "number" && code === wsError_1.ErrorCode.ERR_CONNECTION_CLOSED) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
if (typeof code === "string") {
|
|
271
|
+
const loweredCode = code.toLowerCase();
|
|
272
|
+
if (loweredCode.length > 0 && NETWORK_ERROR_CODES.has(loweredCode)) {
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
const message = err instanceof Error
|
|
277
|
+
? err.message
|
|
278
|
+
: typeof errObj?.message === "string"
|
|
279
|
+
? errObj.message
|
|
280
|
+
: String(err);
|
|
281
|
+
const lowered = message.toLowerCase();
|
|
282
|
+
return NETWORK_ERROR_MESSAGE_PATTERNS.some((pattern) => lowered.includes(pattern));
|
|
283
|
+
}
|
|
284
|
+
send(message, triggerReconnect = true) {
|
|
285
|
+
try {
|
|
286
|
+
this._conn.send(message);
|
|
287
|
+
}
|
|
288
|
+
catch (err) {
|
|
289
|
+
if (triggerReconnect && this.isNetworkError(err)) {
|
|
290
|
+
void this.triggerReconnect().catch((err) => {
|
|
291
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
292
|
+
log_1.default.error(`Reconnect trigger failed: ${message}`);
|
|
293
|
+
});
|
|
98
294
|
}
|
|
99
|
-
|
|
100
|
-
|
|
295
|
+
throw err;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
async ready() {
|
|
299
|
+
if (this._conn && this._conn.readyState === websocket_1.w3cwebsocket.OPEN) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
if (this._reconnectLock) {
|
|
303
|
+
await this._reconnectLock;
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
try {
|
|
307
|
+
await this._connectionReady;
|
|
308
|
+
}
|
|
309
|
+
catch (err) {
|
|
310
|
+
if (this._reconnectLock) {
|
|
311
|
+
await this._reconnectLock;
|
|
312
|
+
return;
|
|
101
313
|
}
|
|
314
|
+
throw err;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
getCurrentAddress() {
|
|
318
|
+
return `${this._currentAddress.host}:${this._currentAddress.port}`;
|
|
319
|
+
}
|
|
320
|
+
selectLeastConnectedAddress(excludedAddresses = new Set()) {
|
|
321
|
+
const candidates = this._dsn.addresses.filter((address) => {
|
|
322
|
+
const addressKey = `${address.host}:${address.port}`;
|
|
323
|
+
return !excludedAddresses.has(addressKey);
|
|
102
324
|
});
|
|
325
|
+
const selectableAddresses = candidates.length > 0 ? candidates : this._dsn.addresses;
|
|
326
|
+
const selectedIndex = addressConnectionTracker_1.AddressConnectionTracker.instance()
|
|
327
|
+
.selectLeastConnected(selectableAddresses);
|
|
328
|
+
return selectableAddresses[selectedIndex];
|
|
103
329
|
}
|
|
104
|
-
async
|
|
105
|
-
|
|
106
|
-
|
|
330
|
+
async sleep(ms) {
|
|
331
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
332
|
+
}
|
|
333
|
+
isReconnectAllowed() {
|
|
334
|
+
return this._allowReconnect;
|
|
335
|
+
}
|
|
336
|
+
async triggerReconnect() {
|
|
337
|
+
if (!this.isReconnectAllowed()) {
|
|
338
|
+
return;
|
|
107
339
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
msg.args.id = BigInt(msg.args.id);
|
|
340
|
+
if (!this._reconnectLock) {
|
|
341
|
+
this._reconnectLock = this._doReconnect();
|
|
111
342
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
343
|
+
const lock = this._reconnectLock;
|
|
344
|
+
try {
|
|
345
|
+
await lock;
|
|
346
|
+
}
|
|
347
|
+
finally {
|
|
348
|
+
if (this._reconnectLock === lock) {
|
|
349
|
+
this._reconnectLock = null;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
async _doReconnect() {
|
|
354
|
+
if (!this.isReconnectAllowed()) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
this._isReconnecting = true;
|
|
358
|
+
try {
|
|
359
|
+
await this.attemptReconnect();
|
|
360
|
+
}
|
|
361
|
+
catch (err) {
|
|
362
|
+
const reconnectError = err instanceof Error
|
|
363
|
+
? err
|
|
364
|
+
: new Error("unknown reconnect error");
|
|
365
|
+
this.failAllInflightRequests(reconnectError);
|
|
366
|
+
throw reconnectError;
|
|
367
|
+
}
|
|
368
|
+
finally {
|
|
369
|
+
this._isReconnecting = false;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
async reconnect() {
|
|
373
|
+
if (this._conn) {
|
|
374
|
+
addressConnectionTracker_1.AddressConnectionTracker.instance().decrement(this.getCurrentAddress());
|
|
375
|
+
this._suppressedSockets.add(this._conn);
|
|
376
|
+
this._conn.close();
|
|
377
|
+
}
|
|
378
|
+
this.createConnection();
|
|
379
|
+
await this._connectionReady;
|
|
380
|
+
}
|
|
381
|
+
async attemptReconnect() {
|
|
382
|
+
const totalAddresses = this._dsn.addresses.length;
|
|
383
|
+
const failedAddresses = new Set();
|
|
384
|
+
for (let i = 0; i < totalAddresses; i++) {
|
|
385
|
+
for (let retry = 0; retry < this._retryConfig.retries; retry++) {
|
|
386
|
+
if (!this.isReconnectAllowed()) {
|
|
387
|
+
return;
|
|
121
388
|
}
|
|
122
|
-
|
|
123
|
-
log_1.default.
|
|
389
|
+
try {
|
|
390
|
+
log_1.default.info(`Reconnecting to ${this.getCurrentAddress()}, attempt ${retry + 1}`);
|
|
391
|
+
await this.reconnect();
|
|
392
|
+
await this.recoverSessionContext();
|
|
393
|
+
await this.replayRequests();
|
|
394
|
+
log_1.default.info(`Reconnection successful to ${this.getCurrentAddress()}`);
|
|
395
|
+
return;
|
|
124
396
|
}
|
|
125
|
-
|
|
397
|
+
catch (err) {
|
|
398
|
+
log_1.default.warn(`Reconnect failed: ${err.message}`);
|
|
399
|
+
if (retry < this._retryConfig.retries - 1) {
|
|
400
|
+
const delay = this._retryConfig.getBackoffDelay(retry);
|
|
401
|
+
await this.sleep(delay);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
if (i < totalAddresses - 1) {
|
|
406
|
+
failedAddresses.add(this.getCurrentAddress());
|
|
407
|
+
this._currentAddress = this.selectLeastConnectedAddress(failedAddresses);
|
|
408
|
+
log_1.default.info(`Switching to least-connected address: ${this.getCurrentAddress()}`);
|
|
126
409
|
}
|
|
127
|
-
|
|
128
|
-
|
|
410
|
+
}
|
|
411
|
+
throw new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_WEBSOCKET_CONNECTION_FAIL, "Failed to reconnect to any available address");
|
|
412
|
+
}
|
|
413
|
+
async replayRequests() {
|
|
414
|
+
log_1.default.info("Replaying requests after reconnection");
|
|
415
|
+
for (const req of this._inflightStore.getRequests()) {
|
|
416
|
+
try {
|
|
417
|
+
this.send(req.message, false);
|
|
418
|
+
}
|
|
419
|
+
catch (err) {
|
|
420
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
421
|
+
if (this.isNetworkError(err)) {
|
|
422
|
+
log_1.default.warn(`Network error while replaying inflight request, stopping current replay round: ${message}`);
|
|
423
|
+
throw err;
|
|
424
|
+
}
|
|
425
|
+
log_1.default.error(`Failed to replay inflight request: ${req}, error: ${message}`);
|
|
426
|
+
req.reject(err);
|
|
129
427
|
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
failAllInflightRequests(error) {
|
|
431
|
+
for (const req of this._inflightStore.getRequests()) {
|
|
432
|
+
req.reject(error);
|
|
433
|
+
}
|
|
434
|
+
this._inflightStore.clear();
|
|
435
|
+
}
|
|
436
|
+
close() {
|
|
437
|
+
this._allowReconnect = false;
|
|
438
|
+
this.failAllInflightRequests(new wsError_1.TDWebSocketClientError(wsError_1.ErrorCode.ERR_CONNECTION_CLOSED, "websocket connection closed"));
|
|
439
|
+
if (this._conn) {
|
|
440
|
+
addressConnectionTracker_1.AddressConnectionTracker.instance().decrement(this.getCurrentAddress());
|
|
441
|
+
this._suppressedSockets.add(this._conn);
|
|
442
|
+
this._conn.close();
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
log_1.default.warn("close() called but websocket connection is undefined");
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
readyState() {
|
|
449
|
+
return this._conn.readyState;
|
|
450
|
+
}
|
|
451
|
+
setSessionRecoveryHook(hook) {
|
|
452
|
+
this._sessionRecoveryHook = hook || null;
|
|
453
|
+
}
|
|
454
|
+
async recoverSessionContext() {
|
|
455
|
+
if (!this._sessionRecoveryHook) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
await this._sessionRecoveryHook();
|
|
459
|
+
}
|
|
460
|
+
async sendMsgDirect(message) {
|
|
461
|
+
if (log_1.default.isDebugEnabled()) {
|
|
462
|
+
log_1.default.debug("[wsClient.sendMsgDirect]===>" + (0, utils_1.maskSensitiveForLog)(message));
|
|
463
|
+
}
|
|
464
|
+
const msg = JSON.parse(message);
|
|
465
|
+
const reqId = this.extractReqId(msg?.args?.req_id) ?? BigInt(0);
|
|
466
|
+
let resolveResp = () => { };
|
|
467
|
+
let rejectResp = () => { };
|
|
468
|
+
const responsePromise = new Promise((resolve, reject) => {
|
|
469
|
+
resolveResp = resolve;
|
|
470
|
+
rejectResp = reject;
|
|
130
471
|
});
|
|
472
|
+
await wsEventCallback_1.WsEventCallback.instance().registerCallback({
|
|
473
|
+
action: msg.action,
|
|
474
|
+
req_id: reqId,
|
|
475
|
+
timeout: this._timeout,
|
|
476
|
+
poolKey: this._poolKey,
|
|
477
|
+
}, resolveResp, rejectResp);
|
|
478
|
+
try {
|
|
479
|
+
this.send(message, false);
|
|
480
|
+
return await responsePromise;
|
|
481
|
+
}
|
|
482
|
+
catch (err) {
|
|
483
|
+
await wsEventCallback_1.WsEventCallback.instance().unregisterCallback(reqId);
|
|
484
|
+
throw err;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
async sendMsgNoResp(message) {
|
|
488
|
+
log_1.default.debug("[wsClient.sendMsgNoResp]===>" + message);
|
|
489
|
+
if (this._reconnectLock) {
|
|
490
|
+
await this._reconnectLock;
|
|
491
|
+
}
|
|
492
|
+
this.send(message);
|
|
493
|
+
}
|
|
494
|
+
async sendMsg(message) {
|
|
495
|
+
if (log_1.default.isDebugEnabled()) {
|
|
496
|
+
log_1.default.debug("[wsConnector.sendMsg]===>" + (0, utils_1.maskSensitiveForLog)(message));
|
|
497
|
+
}
|
|
498
|
+
const msg = JSON.parse(message);
|
|
499
|
+
const id = msg?.args?.id !== undefined ? BigInt(msg.args.id) : undefined;
|
|
500
|
+
const reqId = this.extractReqId(msg?.args?.req_id) ?? BigInt(0);
|
|
501
|
+
return this.sendAndTrackResponse(reqId, msg.action, message, this.isRetriableAction(msg.action), id);
|
|
131
502
|
}
|
|
132
|
-
async sendBinaryMsg(reqId, action, message
|
|
503
|
+
async sendBinaryMsg(reqId, action, message) {
|
|
504
|
+
return this.sendAndTrackResponse(reqId, action, message, this.isRetriableBinaryAction(this.extractBinaryAction(message)), reqId);
|
|
505
|
+
}
|
|
506
|
+
async sendAndTrackResponse(reqId, action, message, retriable, callbackId) {
|
|
507
|
+
if (this._reconnectLock) {
|
|
508
|
+
await this._reconnectLock;
|
|
509
|
+
}
|
|
133
510
|
return new Promise((resolve, reject) => {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
req_id: reqId,
|
|
139
|
-
timeout: this._timeout,
|
|
140
|
-
id: reqId,
|
|
141
|
-
}, resolve, reject);
|
|
511
|
+
let settled = false;
|
|
512
|
+
const safeResolve = (result) => {
|
|
513
|
+
if (settled) {
|
|
514
|
+
return;
|
|
142
515
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
516
|
+
settled = true;
|
|
517
|
+
if (retriable) {
|
|
518
|
+
this._inflightStore.remove(reqId);
|
|
519
|
+
}
|
|
520
|
+
resolve(result);
|
|
521
|
+
};
|
|
522
|
+
const safeReject = (error) => {
|
|
523
|
+
if (settled) {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
settled = true;
|
|
527
|
+
if (retriable) {
|
|
528
|
+
this._inflightStore.remove(reqId);
|
|
529
|
+
}
|
|
530
|
+
void wsEventCallback_1.WsEventCallback.instance().unregisterCallback(reqId);
|
|
531
|
+
reject(error);
|
|
532
|
+
};
|
|
533
|
+
const registerAndSend = async () => {
|
|
534
|
+
if (retriable) {
|
|
535
|
+
this._inflightStore.insert({
|
|
536
|
+
reqId,
|
|
537
|
+
action,
|
|
538
|
+
id: callbackId,
|
|
539
|
+
message,
|
|
540
|
+
resolve: safeResolve,
|
|
541
|
+
reject: safeReject,
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
await wsEventCallback_1.WsEventCallback.instance().registerCallback({
|
|
545
|
+
action,
|
|
546
|
+
req_id: reqId,
|
|
547
|
+
timeout: this._timeout,
|
|
548
|
+
id: callbackId,
|
|
549
|
+
poolKey: this._poolKey,
|
|
550
|
+
}, safeResolve, safeReject);
|
|
551
|
+
if (settled) {
|
|
552
|
+
await wsEventCallback_1.WsEventCallback.instance().unregisterCallback(reqId);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
try {
|
|
556
|
+
this.send(message);
|
|
557
|
+
}
|
|
558
|
+
catch (err) {
|
|
559
|
+
if (retriable && this.isNetworkError(err)) {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
safeReject(err);
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
void registerAndSend().catch((error) => {
|
|
566
|
+
safeReject(error);
|
|
567
|
+
});
|
|
152
568
|
});
|
|
153
569
|
}
|
|
154
|
-
|
|
155
|
-
return this.
|
|
570
|
+
getPoolKey() {
|
|
571
|
+
return this._poolKey;
|
|
572
|
+
}
|
|
573
|
+
getReconnectRetries() {
|
|
574
|
+
return this._retryConfig.retries;
|
|
156
575
|
}
|
|
157
576
|
}
|
|
158
577
|
exports.WebSocketConnector = WebSocketConnector;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Dsn } from "../common/dsn";
|
|
1
2
|
import { WebSocketConnector } from "./wsConnector";
|
|
2
3
|
export declare class WebSocketConnectionPool {
|
|
3
4
|
private static _instance?;
|
|
@@ -7,7 +8,10 @@ export declare class WebSocketConnectionPool {
|
|
|
7
8
|
private static sharedArray;
|
|
8
9
|
private constructor();
|
|
9
10
|
static instance(maxConnections?: number): WebSocketConnectionPool;
|
|
10
|
-
|
|
11
|
+
private maskPoolKeyForLog;
|
|
12
|
+
private buildAuthScope;
|
|
13
|
+
private getPoolKey;
|
|
14
|
+
getConnection(dsn: Dsn, timeout: number | undefined | null): Promise<WebSocketConnector>;
|
|
11
15
|
releaseConnection(connector: WebSocketConnector): Promise<void>;
|
|
12
16
|
destroyed(): void;
|
|
13
17
|
}
|