@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
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const wsConnectorPool_1 = require("@src/client/wsConnectorPool");
|
|
4
|
+
const config_1 = require("@src/common/config");
|
|
5
|
+
const wsSql_1 = require("@src/sql/wsSql");
|
|
6
|
+
const utils_1 = require("@test-helpers/utils");
|
|
7
|
+
const wsProxy_1 = require("@test-helpers/wsProxy");
|
|
8
|
+
function parseJsonAction(rawData) {
|
|
9
|
+
if (typeof rawData !== "string") {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const parsed = JSON.parse(rawData);
|
|
14
|
+
return typeof parsed.action === "string" ? parsed.action : null;
|
|
15
|
+
}
|
|
16
|
+
catch (_err) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function parseBinaryAction(rawData) {
|
|
21
|
+
if (typeof rawData === "string" || rawData.byteLength < 24) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
return rawData.readBigInt64LE(16);
|
|
25
|
+
}
|
|
26
|
+
function asClientToUpstreamMessage(event) {
|
|
27
|
+
if (event.type !== "message") {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
if (event.direction !== "client_to_upstream") {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return event;
|
|
34
|
+
}
|
|
35
|
+
const stageCases = [
|
|
36
|
+
{
|
|
37
|
+
name: "init",
|
|
38
|
+
shouldRestart: (event) => {
|
|
39
|
+
const messageEvent = asClientToUpstreamMessage(event);
|
|
40
|
+
return !!messageEvent &&
|
|
41
|
+
parseJsonAction(messageEvent.rawData) === "stmt2_init";
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: "prepare",
|
|
46
|
+
shouldRestart: (event) => {
|
|
47
|
+
const messageEvent = asClientToUpstreamMessage(event);
|
|
48
|
+
return !!messageEvent &&
|
|
49
|
+
parseJsonAction(messageEvent.rawData) === "stmt2_prepare";
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "bind",
|
|
54
|
+
shouldRestart: (event) => {
|
|
55
|
+
const messageEvent = asClientToUpstreamMessage(event);
|
|
56
|
+
return !!messageEvent &&
|
|
57
|
+
messageEvent.isBinary &&
|
|
58
|
+
parseBinaryAction(messageEvent.rawData) === 9n;
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "exec",
|
|
63
|
+
shouldRestart: (event) => {
|
|
64
|
+
const messageEvent = asClientToUpstreamMessage(event);
|
|
65
|
+
return !!messageEvent &&
|
|
66
|
+
parseJsonAction(messageEvent.rawData) === "stmt2_exec";
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "result",
|
|
71
|
+
shouldRestart: (event) => {
|
|
72
|
+
const messageEvent = asClientToUpstreamMessage(event);
|
|
73
|
+
return !!messageEvent &&
|
|
74
|
+
parseJsonAction(messageEvent.rawData) === "stmt2_result";
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
describe("stmt2 failover with ws proxy", () => {
|
|
79
|
+
jest.setTimeout(180 * 1000);
|
|
80
|
+
afterEach(async () => {
|
|
81
|
+
wsConnectorPool_1.WebSocketConnectionPool.instance().destroyed();
|
|
82
|
+
jest.restoreAllMocks();
|
|
83
|
+
});
|
|
84
|
+
test.each(stageCases)("single-address reconnect recovers stmt2 when network error happens at $name stage", async ({ name, shouldRestart }) => {
|
|
85
|
+
const dbName = `test_1774332664_${name}`;
|
|
86
|
+
const tableName = "t0";
|
|
87
|
+
const baseTs = 1700100000000;
|
|
88
|
+
const localDsn = `ws://${(0, utils_1.testUsername)()}:${(0, utils_1.testPassword)()}@127.0.0.1:6041`;
|
|
89
|
+
let setupSql = null;
|
|
90
|
+
let cleanupSql = null;
|
|
91
|
+
let wsSql = null;
|
|
92
|
+
let stmt = null;
|
|
93
|
+
let wsRows = null;
|
|
94
|
+
let restartTriggered = false;
|
|
95
|
+
let clientConnectedCount = 0;
|
|
96
|
+
let matchedStageMessageCount = 0;
|
|
97
|
+
let rowCount = 0;
|
|
98
|
+
setupSql = await wsSql_1.WsSql.open(new config_1.WSConfig(localDsn));
|
|
99
|
+
try {
|
|
100
|
+
await setupSql.exec(`drop database if exists ${dbName}`);
|
|
101
|
+
await setupSql.exec(`create database ${dbName}`);
|
|
102
|
+
await setupSql.exec(`create table ${dbName}.${tableName}(ts timestamp, c1 int)`);
|
|
103
|
+
await setupSql.exec(`insert into ${dbName}.${tableName} values` +
|
|
104
|
+
` (${baseTs}, 1) (${baseTs + 1}, 2) (${baseTs + 2}, 3)`);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
await setupSql.close();
|
|
108
|
+
setupSql = null;
|
|
109
|
+
}
|
|
110
|
+
const proxy = await wsProxy_1.WsProxy.create({
|
|
111
|
+
host: "127.0.0.1",
|
|
112
|
+
port: 0,
|
|
113
|
+
onEvent: (event, control) => {
|
|
114
|
+
if (event.type === "client_connected") {
|
|
115
|
+
clientConnectedCount += 1;
|
|
116
|
+
}
|
|
117
|
+
if (restartTriggered) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!shouldRestart(event)) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
matchedStageMessageCount += 1;
|
|
124
|
+
restartTriggered = true;
|
|
125
|
+
void control.restart({
|
|
126
|
+
downtimeMs: 200,
|
|
127
|
+
reason: `trigger stmt2 ${name} failover`,
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
try {
|
|
132
|
+
const dsn = `ws://${(0, utils_1.testUsername)()}:${(0, utils_1.testPassword)()}@127.0.0.1:${proxy.getPort()}` +
|
|
133
|
+
`?retries=20&retry_backoff_ms=15&retry_backoff_max_ms=80`;
|
|
134
|
+
const conf = new config_1.WSConfig(dsn);
|
|
135
|
+
conf.setDb(dbName);
|
|
136
|
+
wsSql = await wsSql_1.WsSql.open(conf);
|
|
137
|
+
stmt = await wsSql.stmtInit();
|
|
138
|
+
await stmt.prepare(`select ts, c1 from ${tableName} where ts >= ? and ts <= ? order by ts`);
|
|
139
|
+
const params = stmt.newStmtParam();
|
|
140
|
+
params.setTimestamp([BigInt(baseTs)]);
|
|
141
|
+
params.setTimestamp([BigInt(baseTs + 2)]);
|
|
142
|
+
await stmt.bind(params);
|
|
143
|
+
await stmt.exec();
|
|
144
|
+
wsRows = await stmt.resultSet();
|
|
145
|
+
while (await wsRows.next()) {
|
|
146
|
+
const data = wsRows.getData();
|
|
147
|
+
expect(data).toBeTruthy();
|
|
148
|
+
rowCount += 1;
|
|
149
|
+
}
|
|
150
|
+
expect(matchedStageMessageCount).toBe(1);
|
|
151
|
+
expect(restartTriggered).toBe(true);
|
|
152
|
+
expect(clientConnectedCount).toBeGreaterThanOrEqual(2);
|
|
153
|
+
expect(rowCount).toBe(3);
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
if (wsRows) {
|
|
157
|
+
try {
|
|
158
|
+
await wsRows.close();
|
|
159
|
+
}
|
|
160
|
+
catch (_err) {
|
|
161
|
+
// ignore cleanup error
|
|
162
|
+
}
|
|
163
|
+
wsRows = null;
|
|
164
|
+
}
|
|
165
|
+
if (stmt) {
|
|
166
|
+
try {
|
|
167
|
+
await stmt.close();
|
|
168
|
+
}
|
|
169
|
+
catch (_err) {
|
|
170
|
+
// ignore cleanup error
|
|
171
|
+
}
|
|
172
|
+
stmt = null;
|
|
173
|
+
}
|
|
174
|
+
if (wsSql) {
|
|
175
|
+
await wsSql.close();
|
|
176
|
+
wsSql = null;
|
|
177
|
+
}
|
|
178
|
+
await proxy.stop("test cleanup");
|
|
179
|
+
cleanupSql = await wsSql_1.WsSql.open(new config_1.WSConfig(localDsn));
|
|
180
|
+
try {
|
|
181
|
+
await cleanupSql.exec(`drop database if exists ${dbName}`);
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
await cleanupSql.close();
|
|
185
|
+
cleanupSql = null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
test("single-address random proxy restarts on stmt2 steps still keeps all 5000 inserted rows", async () => {
|
|
190
|
+
const targetRows = 5000;
|
|
191
|
+
const batchSize = 50;
|
|
192
|
+
const baseTs = 1700110000000;
|
|
193
|
+
const dbName = "test_1774338668";
|
|
194
|
+
const stableName = "meters";
|
|
195
|
+
const subTableName = "d0";
|
|
196
|
+
const fullSubTableName = `${dbName}.${subTableName}`;
|
|
197
|
+
const localDsn = `ws://${(0, utils_1.testUsername)()}:${(0, utils_1.testPassword)()}@127.0.0.1:6041`;
|
|
198
|
+
let setupSql = null;
|
|
199
|
+
let cleanupSql = null;
|
|
200
|
+
let wsSql = null;
|
|
201
|
+
let insertStmt = null;
|
|
202
|
+
let countStmt = null;
|
|
203
|
+
let countRows = null;
|
|
204
|
+
let writePhase = false;
|
|
205
|
+
let verifyPhase = false;
|
|
206
|
+
let restartInFlight = false;
|
|
207
|
+
let restartCount = 0;
|
|
208
|
+
let rowCount = 0;
|
|
209
|
+
const stepSeenCount = {
|
|
210
|
+
init: 0,
|
|
211
|
+
prepare: 0,
|
|
212
|
+
bind: 0,
|
|
213
|
+
exec: 0,
|
|
214
|
+
result: 0,
|
|
215
|
+
};
|
|
216
|
+
setupSql = await wsSql_1.WsSql.open(new config_1.WSConfig(localDsn));
|
|
217
|
+
try {
|
|
218
|
+
await setupSql.exec(`drop database if exists ${dbName}`);
|
|
219
|
+
await setupSql.exec(`create database ${dbName}`);
|
|
220
|
+
await setupSql.exec(`create stable ${dbName}.${stableName}(ts timestamp, c1 int)` +
|
|
221
|
+
` tags(location binary(64), gid int)`);
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
await setupSql.close();
|
|
225
|
+
setupSql = null;
|
|
226
|
+
}
|
|
227
|
+
const proxy = await wsProxy_1.WsProxy.create({
|
|
228
|
+
host: "127.0.0.1",
|
|
229
|
+
port: 0,
|
|
230
|
+
onEvent: (event, control) => {
|
|
231
|
+
const messageEvent = asClientToUpstreamMessage(event);
|
|
232
|
+
if (!messageEvent) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
let step = null;
|
|
236
|
+
if (messageEvent.isBinary) {
|
|
237
|
+
const action = parseBinaryAction(messageEvent.rawData);
|
|
238
|
+
if (action === 9n) {
|
|
239
|
+
step = "bind";
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
const action = parseJsonAction(messageEvent.rawData);
|
|
244
|
+
if (action === "stmt2_init") {
|
|
245
|
+
step = "init";
|
|
246
|
+
}
|
|
247
|
+
else if (action === "stmt2_prepare") {
|
|
248
|
+
step = "prepare";
|
|
249
|
+
}
|
|
250
|
+
else if (action === "stmt2_exec") {
|
|
251
|
+
step = "exec";
|
|
252
|
+
}
|
|
253
|
+
else if (action === "stmt2_result") {
|
|
254
|
+
step = "result";
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (!step) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
stepSeenCount[step] += 1;
|
|
261
|
+
if (!writePhase && !verifyPhase) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (restartInFlight) {
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const shouldRestart = Math.random() < 0.05 ||
|
|
268
|
+
(restartCount === 0 && step === "bind");
|
|
269
|
+
if (!shouldRestart) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
restartInFlight = true;
|
|
273
|
+
restartCount += 1;
|
|
274
|
+
const downtimeMs = 20 + Math.floor(Math.random() * 100);
|
|
275
|
+
void control.restart({
|
|
276
|
+
downtimeMs,
|
|
277
|
+
reason: `stmt2 random step restart #${restartCount} (${step})`,
|
|
278
|
+
}).finally(() => {
|
|
279
|
+
restartInFlight = false;
|
|
280
|
+
});
|
|
281
|
+
},
|
|
282
|
+
});
|
|
283
|
+
try {
|
|
284
|
+
const dsn = `ws://${(0, utils_1.testUsername)()}:${(0, utils_1.testPassword)()}@127.0.0.1:${proxy.getPort()}` +
|
|
285
|
+
`?retries=80&retry_backoff_ms=10&retry_backoff_max_ms=50`;
|
|
286
|
+
const conf = new config_1.WSConfig(dsn);
|
|
287
|
+
conf.setDb(dbName);
|
|
288
|
+
wsSql = await wsSql_1.WsSql.open(conf);
|
|
289
|
+
insertStmt = await wsSql.stmtInit();
|
|
290
|
+
const insertSql = `insert into ? using ${stableName} (location, gid) tags (?, ?) values(?, ?)`;
|
|
291
|
+
await insertStmt.prepare(insertSql);
|
|
292
|
+
writePhase = true;
|
|
293
|
+
for (let start = 0; start < targetRows; start += batchSize) {
|
|
294
|
+
const end = Math.min(start + batchSize, targetRows);
|
|
295
|
+
const tsBatch = [];
|
|
296
|
+
const c1Batch = [];
|
|
297
|
+
for (let i = start; i < end; i++) {
|
|
298
|
+
tsBatch.push(BigInt(baseTs + i));
|
|
299
|
+
c1Batch.push(i);
|
|
300
|
+
}
|
|
301
|
+
await insertStmt.setTableName(fullSubTableName);
|
|
302
|
+
const tagParams = insertStmt.newStmtParam();
|
|
303
|
+
tagParams.setVarchar(["beijing"]);
|
|
304
|
+
tagParams.setInt([1]);
|
|
305
|
+
await insertStmt.setTags(tagParams);
|
|
306
|
+
const params = insertStmt.newStmtParam();
|
|
307
|
+
params.setTimestamp(tsBatch);
|
|
308
|
+
params.setInt(c1Batch);
|
|
309
|
+
await insertStmt.bind(params);
|
|
310
|
+
await insertStmt.exec();
|
|
311
|
+
}
|
|
312
|
+
writePhase = false;
|
|
313
|
+
verifyPhase = true;
|
|
314
|
+
countStmt = await wsSql.stmtInit();
|
|
315
|
+
await countStmt.prepare(`select ts, c1 from ${subTableName} where ts >= ? and ts <= ? order by ts limit 1`);
|
|
316
|
+
const countParams = countStmt.newStmtParam();
|
|
317
|
+
countParams.setTimestamp([BigInt(baseTs)]);
|
|
318
|
+
countParams.setTimestamp([BigInt(baseTs + targetRows - 1)]);
|
|
319
|
+
await countStmt.bind(countParams);
|
|
320
|
+
await countStmt.exec();
|
|
321
|
+
countRows = await countStmt.resultSet();
|
|
322
|
+
if (await countRows.next()) {
|
|
323
|
+
expect(countRows.getData()).toBeTruthy();
|
|
324
|
+
}
|
|
325
|
+
verifyPhase = false;
|
|
326
|
+
const countResult = await wsSql.exec(`select count(*) from ${subTableName}`);
|
|
327
|
+
const countValue = countResult.getData()?.[0]?.[0];
|
|
328
|
+
rowCount = typeof countValue === "bigint"
|
|
329
|
+
? Number(countValue)
|
|
330
|
+
: Number(countValue || 0);
|
|
331
|
+
expect(rowCount).toBe(targetRows);
|
|
332
|
+
expect(restartCount).toBeGreaterThan(0);
|
|
333
|
+
expect(stepSeenCount.init).toBeGreaterThan(0);
|
|
334
|
+
expect(stepSeenCount.prepare).toBeGreaterThan(0);
|
|
335
|
+
expect(stepSeenCount.bind).toBeGreaterThan(0);
|
|
336
|
+
expect(stepSeenCount.exec).toBeGreaterThan(0);
|
|
337
|
+
expect(stepSeenCount.result).toBeGreaterThan(0);
|
|
338
|
+
}
|
|
339
|
+
finally {
|
|
340
|
+
writePhase = false;
|
|
341
|
+
verifyPhase = false;
|
|
342
|
+
if (countRows) {
|
|
343
|
+
try {
|
|
344
|
+
await countRows.close();
|
|
345
|
+
}
|
|
346
|
+
catch (_err) {
|
|
347
|
+
// ignore cleanup error
|
|
348
|
+
}
|
|
349
|
+
countRows = null;
|
|
350
|
+
}
|
|
351
|
+
if (countStmt) {
|
|
352
|
+
try {
|
|
353
|
+
await countStmt.close();
|
|
354
|
+
}
|
|
355
|
+
catch (_err) {
|
|
356
|
+
// ignore cleanup error
|
|
357
|
+
}
|
|
358
|
+
countStmt = null;
|
|
359
|
+
}
|
|
360
|
+
if (insertStmt) {
|
|
361
|
+
try {
|
|
362
|
+
await insertStmt.close();
|
|
363
|
+
}
|
|
364
|
+
catch (_err) {
|
|
365
|
+
// ignore cleanup error
|
|
366
|
+
}
|
|
367
|
+
insertStmt = null;
|
|
368
|
+
}
|
|
369
|
+
if (wsSql) {
|
|
370
|
+
await wsSql.close();
|
|
371
|
+
wsSql = null;
|
|
372
|
+
}
|
|
373
|
+
await proxy.stop("test cleanup");
|
|
374
|
+
cleanupSql = await wsSql_1.WsSql.open(new config_1.WSConfig(localDsn));
|
|
375
|
+
try {
|
|
376
|
+
await cleanupSql.exec(`drop database if exists ${dbName}`);
|
|
377
|
+
}
|
|
378
|
+
finally {
|
|
379
|
+
await cleanupSql.close();
|
|
380
|
+
cleanupSql = null;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}, 300 * 1000);
|
|
384
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stmt2.func.test.d.ts","sourceRoot":"","sources":["../../../test/stmt/stmt2.func.test.ts"],"names":[],"mappings":""}
|