@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.
Files changed (224) hide show
  1. package/lib/package.json +1 -1
  2. package/lib/src/client/wsClient.d.ts +23 -7
  3. package/lib/src/client/wsClient.d.ts.map +1 -1
  4. package/lib/src/client/wsClient.js +154 -139
  5. package/lib/src/client/wsConnector.d.ts +55 -9
  6. package/lib/src/client/wsConnector.d.ts.map +1 -1
  7. package/lib/src/client/wsConnector.js +519 -100
  8. package/lib/src/client/wsConnectorPool.d.ts +5 -1
  9. package/lib/src/client/wsConnectorPool.d.ts.map +1 -1
  10. package/lib/src/client/wsConnectorPool.js +61 -43
  11. package/lib/src/client/wsEventCallback.d.ts +3 -0
  12. package/lib/src/client/wsEventCallback.d.ts.map +1 -1
  13. package/lib/src/client/wsEventCallback.js +67 -8
  14. package/lib/src/common/addressConnectionTracker.d.ts +11 -0
  15. package/lib/src/common/addressConnectionTracker.d.ts.map +1 -0
  16. package/lib/src/common/addressConnectionTracker.js +53 -0
  17. package/lib/src/common/dsn.d.ts +14 -2
  18. package/lib/src/common/dsn.d.ts.map +1 -1
  19. package/lib/src/common/dsn.js +91 -22
  20. package/lib/src/common/taosResult.d.ts.map +1 -1
  21. package/lib/src/common/taosResult.js +0 -5
  22. package/lib/src/common/urlParser.d.ts +32 -0
  23. package/lib/src/common/urlParser.d.ts.map +1 -0
  24. package/lib/src/common/urlParser.js +201 -0
  25. package/lib/src/common/utils.d.ts +2 -1
  26. package/lib/src/common/utils.d.ts.map +1 -1
  27. package/lib/src/common/utils.js +35 -34
  28. package/lib/src/sql/wsSql.js +2 -2
  29. package/lib/src/stmt/FieldBindParams.d.ts.map +1 -1
  30. package/lib/src/stmt/wsColumnInfo.d.ts.map +1 -1
  31. package/lib/src/stmt/wsParams1.d.ts.map +1 -1
  32. package/lib/src/stmt/wsParams1.js +26 -26
  33. package/lib/src/stmt/wsParams2.d.ts.map +1 -1
  34. package/lib/src/stmt/wsParams2.js +0 -3
  35. package/lib/src/stmt/wsParamsBase.d.ts.map +1 -1
  36. package/lib/src/stmt/wsProto.d.ts.map +1 -1
  37. package/lib/src/stmt/wsProto.js +16 -16
  38. package/lib/src/stmt/wsStmt1.d.ts.map +1 -1
  39. package/lib/src/stmt/wsStmt2.d.ts +12 -4
  40. package/lib/src/stmt/wsStmt2.d.ts.map +1 -1
  41. package/lib/src/stmt/wsStmt2.js +182 -64
  42. package/lib/src/stmt/wsTableInfo.d.ts.map +1 -1
  43. package/lib/src/tmq/config.d.ts +3 -2
  44. package/lib/src/tmq/config.d.ts.map +1 -1
  45. package/lib/src/tmq/config.js +15 -15
  46. package/lib/src/tmq/wsTmq.d.ts +4 -1
  47. package/lib/src/tmq/wsTmq.d.ts.map +1 -1
  48. package/lib/src/tmq/wsTmq.js +50 -27
  49. package/lib/test/bulkPulling/a.test.d.ts +2 -0
  50. package/lib/test/bulkPulling/a.test.d.ts.map +1 -0
  51. package/lib/test/bulkPulling/a.test.js +166 -0
  52. package/lib/test/bulkPulling/dsn.test.js +19 -0
  53. package/lib/test/bulkPulling/retryConfig.test.js +11 -11
  54. package/lib/test/bulkPulling/sql.failover.test.d.ts +2 -0
  55. package/lib/test/bulkPulling/sql.failover.test.d.ts.map +1 -0
  56. package/lib/test/bulkPulling/sql.failover.test.js +338 -0
  57. package/lib/test/bulkPulling/stmt2.failover.test.d.ts +2 -0
  58. package/lib/test/bulkPulling/stmt2.failover.test.d.ts.map +1 -0
  59. package/lib/test/bulkPulling/stmt2.failover.test.js +313 -0
  60. package/lib/test/bulkPulling/stmt2.init.failover.test.d.ts +2 -0
  61. package/lib/test/bulkPulling/stmt2.init.failover.test.d.ts.map +1 -0
  62. package/lib/test/bulkPulling/stmt2.init.failover.test.js +50 -0
  63. package/lib/test/bulkPulling/tmq.failover.test.d.ts +2 -0
  64. package/lib/test/bulkPulling/tmq.failover.test.d.ts.map +1 -0
  65. package/lib/test/bulkPulling/tmq.failover.test.js +404 -0
  66. package/lib/test/bulkPulling/urlParser.test.d.ts +2 -0
  67. package/lib/test/bulkPulling/urlParser.test.d.ts.map +1 -0
  68. package/lib/test/bulkPulling/urlParser.test.js +452 -0
  69. package/lib/test/bulkPulling/wsClient.reconnect.integration.test.js +2 -2
  70. package/lib/test/bulkPulling/wsClient.recovery.test.d.ts +2 -0
  71. package/lib/test/bulkPulling/wsClient.recovery.test.d.ts.map +1 -0
  72. package/lib/test/bulkPulling/wsClient.recovery.test.js +104 -0
  73. package/lib/test/bulkPulling/wsConfig.dsn.test.js +2 -0
  74. package/lib/test/bulkPulling/wsConnector.failover.test.js +396 -27
  75. package/lib/test/bulkPulling/wsConnectorPool.key.test.js +12 -10
  76. package/lib/test/bulkPulling/wsConnectorPool.keyAuth.test.d.ts +2 -0
  77. package/lib/test/bulkPulling/wsConnectorPool.keyAuth.test.d.ts.map +1 -0
  78. package/lib/test/bulkPulling/wsConnectorPool.keyAuth.test.js +28 -0
  79. package/lib/test/bulkPulling/wsProxy.failover.integration.test.d.ts +2 -0
  80. package/lib/test/bulkPulling/wsProxy.failover.integration.test.d.ts.map +1 -0
  81. package/lib/test/bulkPulling/wsProxy.failover.integration.test.js +120 -0
  82. package/lib/test/bulkPulling/wsProxy.failover.test.d.ts +2 -0
  83. package/lib/test/bulkPulling/wsProxy.failover.test.d.ts.map +1 -0
  84. package/lib/test/bulkPulling/wsProxy.failover.test.js +465 -0
  85. package/lib/test/client/wsClient.recovery.test.d.ts +2 -0
  86. package/lib/test/client/wsClient.recovery.test.d.ts.map +1 -0
  87. package/lib/test/client/wsClient.recovery.test.js +122 -0
  88. package/lib/test/client/wsConnectPool.test.d.ts +2 -0
  89. package/lib/test/client/wsConnectPool.test.d.ts.map +1 -0
  90. package/lib/test/client/wsConnectPool.test.js +147 -0
  91. package/lib/test/client/wsConnector.failover.test.d.ts +2 -0
  92. package/lib/test/client/wsConnector.failover.test.d.ts.map +1 -0
  93. package/lib/test/client/wsConnector.failover.test.js +681 -0
  94. package/lib/test/client/wsConnector.leastConnections.test.d.ts +2 -0
  95. package/lib/test/client/wsConnector.leastConnections.test.d.ts.map +1 -0
  96. package/lib/test/client/wsConnector.leastConnections.test.js +71 -0
  97. package/lib/test/client/wsConnectorPool.key.test.d.ts +2 -0
  98. package/lib/test/client/wsConnectorPool.key.test.d.ts.map +1 -0
  99. package/lib/test/client/wsConnectorPool.key.test.js +127 -0
  100. package/lib/test/client/wsEventCallback.test.d.ts +2 -0
  101. package/lib/test/client/wsEventCallback.test.d.ts.map +1 -0
  102. package/lib/test/client/wsEventCallback.test.js +98 -0
  103. package/lib/test/common/addressConnectionTracker.test.d.ts +2 -0
  104. package/lib/test/common/addressConnectionTracker.test.d.ts.map +1 -0
  105. package/lib/test/common/addressConnectionTracker.test.js +74 -0
  106. package/lib/test/common/dsn.test.d.ts +2 -0
  107. package/lib/test/common/dsn.test.d.ts.map +1 -0
  108. package/lib/test/common/dsn.test.js +406 -0
  109. package/lib/test/common/log.test.d.ts +2 -0
  110. package/lib/test/common/log.test.d.ts.map +1 -0
  111. package/lib/test/common/log.test.js +54 -0
  112. package/lib/test/common/utils.test.d.ts +2 -0
  113. package/lib/test/common/utils.test.d.ts.map +1 -0
  114. package/lib/test/common/utils.test.js +13 -0
  115. package/lib/test/common/wsConfig.dsn.test.d.ts +2 -0
  116. package/lib/test/common/wsConfig.dsn.test.d.ts.map +1 -0
  117. package/lib/test/common/wsConfig.dsn.test.js +39 -0
  118. package/lib/test/helpers/utils.d.ts +27 -0
  119. package/lib/test/helpers/utils.d.ts.map +1 -0
  120. package/lib/test/helpers/utils.js +341 -0
  121. package/lib/test/helpers/wsFailoverProxy.d.ts +109 -0
  122. package/lib/test/helpers/wsFailoverProxy.d.ts.map +1 -0
  123. package/lib/test/helpers/wsFailoverProxy.js +420 -0
  124. package/lib/test/helpers/wsProxy.d.ts +110 -0
  125. package/lib/test/helpers/wsProxy.d.ts.map +1 -0
  126. package/lib/test/helpers/wsProxy.js +429 -0
  127. package/lib/test/sql/core/decimal.test.d.ts +2 -0
  128. package/lib/test/sql/core/decimal.test.d.ts.map +1 -0
  129. package/lib/test/sql/core/decimal.test.js +153 -0
  130. package/lib/test/sql/core/queryTables.test.d.ts +2 -0
  131. package/lib/test/sql/core/queryTables.test.d.ts.map +1 -0
  132. package/lib/test/sql/core/queryTables.test.js +506 -0
  133. package/lib/test/sql/core/schemaless.test.d.ts +2 -0
  134. package/lib/test/sql/core/schemaless.test.d.ts.map +1 -0
  135. package/lib/test/sql/core/schemaless.test.js +102 -0
  136. package/lib/test/sql/core/sql.test.d.ts +2 -0
  137. package/lib/test/sql/core/sql.test.d.ts.map +1 -0
  138. package/lib/test/sql/core/sql.test.js +324 -0
  139. package/lib/test/sql/decimal.test.d.ts +2 -0
  140. package/lib/test/sql/decimal.test.d.ts.map +1 -0
  141. package/lib/test/sql/decimal.test.js +153 -0
  142. package/lib/test/sql/failover/sql.failover.test.d.ts +2 -0
  143. package/lib/test/sql/failover/sql.failover.test.d.ts.map +1 -0
  144. package/lib/test/sql/failover/sql.failover.test.js +341 -0
  145. package/lib/test/sql/queryTables.test.d.ts +2 -0
  146. package/lib/test/sql/queryTables.test.d.ts.map +1 -0
  147. package/lib/test/sql/queryTables.test.js +506 -0
  148. package/lib/test/sql/schemaless.test.d.ts +2 -0
  149. package/lib/test/sql/schemaless.test.d.ts.map +1 -0
  150. package/lib/test/sql/schemaless.test.js +102 -0
  151. package/lib/test/sql/sql.failover.test.d.ts +2 -0
  152. package/lib/test/sql/sql.failover.test.d.ts.map +1 -0
  153. package/lib/test/sql/sql.failover.test.js +341 -0
  154. package/lib/test/sql/sql.test.d.ts +2 -0
  155. package/lib/test/sql/sql.test.d.ts.map +1 -0
  156. package/lib/test/sql/sql.test.js +324 -0
  157. package/lib/test/stmt/failover/stmt2.failover.mock.test.d.ts +2 -0
  158. package/lib/test/stmt/failover/stmt2.failover.mock.test.d.ts.map +1 -0
  159. package/lib/test/stmt/failover/stmt2.failover.mock.test.js +341 -0
  160. package/lib/test/stmt/failover/stmt2.failover.test.d.ts +2 -0
  161. package/lib/test/stmt/failover/stmt2.failover.test.d.ts.map +1 -0
  162. package/lib/test/stmt/failover/stmt2.failover.test.js +384 -0
  163. package/lib/test/stmt/stmt1.func.test.d.ts +2 -0
  164. package/lib/test/stmt/stmt1.func.test.d.ts.map +1 -0
  165. package/lib/test/stmt/stmt1.func.test.js +418 -0
  166. package/lib/test/stmt/stmt1.type.test.d.ts +2 -0
  167. package/lib/test/stmt/stmt1.type.test.d.ts.map +1 -0
  168. package/lib/test/stmt/stmt1.type.test.js +399 -0
  169. package/lib/test/stmt/stmt2.failover.mock.test.d.ts +2 -0
  170. package/lib/test/stmt/stmt2.failover.mock.test.d.ts.map +1 -0
  171. package/lib/test/stmt/stmt2.failover.mock.test.js +341 -0
  172. package/lib/test/stmt/stmt2.failover.test.d.ts +2 -0
  173. package/lib/test/stmt/stmt2.failover.test.d.ts.map +1 -0
  174. package/lib/test/stmt/stmt2.failover.test.js +384 -0
  175. package/lib/test/stmt/stmt2.func.test.d.ts +2 -0
  176. package/lib/test/stmt/stmt2.func.test.d.ts.map +1 -0
  177. package/lib/test/stmt/stmt2.func.test.js +537 -0
  178. package/lib/test/stmt/stmt2.type.test.d.ts +2 -0
  179. package/lib/test/stmt/stmt2.type.test.d.ts.map +1 -0
  180. package/lib/test/stmt/stmt2.type.test.js +401 -0
  181. package/lib/test/stmt/v1/stmt1.func.test.d.ts +2 -0
  182. package/lib/test/stmt/v1/stmt1.func.test.d.ts.map +1 -0
  183. package/lib/test/stmt/v1/stmt1.func.test.js +418 -0
  184. package/lib/test/stmt/v1/stmt1.type.test.d.ts +2 -0
  185. package/lib/test/stmt/v1/stmt1.type.test.d.ts.map +1 -0
  186. package/lib/test/stmt/v1/stmt1.type.test.js +399 -0
  187. package/lib/test/stmt/v2/stmt2.func.test.d.ts +2 -0
  188. package/lib/test/stmt/v2/stmt2.func.test.d.ts.map +1 -0
  189. package/lib/test/stmt/v2/stmt2.func.test.js +537 -0
  190. package/lib/test/stmt/v2/stmt2.type.test.d.ts +2 -0
  191. package/lib/test/stmt/v2/stmt2.type.test.d.ts.map +1 -0
  192. package/lib/test/stmt/v2/stmt2.type.test.js +401 -0
  193. package/lib/test/tmq/cloud/cloud.tmq.test.d.ts +2 -0
  194. package/lib/test/tmq/cloud/cloud.tmq.test.d.ts.map +1 -0
  195. package/lib/test/tmq/cloud/cloud.tmq.test.js +84 -0
  196. package/lib/test/tmq/cloud/tmq.cloud.test.d.ts +2 -0
  197. package/lib/test/tmq/cloud/tmq.cloud.test.d.ts.map +1 -0
  198. package/lib/test/tmq/cloud/tmq.cloud.test.js +82 -0
  199. package/lib/test/tmq/core/tmq.config.test.d.ts +2 -0
  200. package/lib/test/tmq/core/tmq.config.test.d.ts.map +1 -0
  201. package/lib/test/tmq/core/tmq.config.test.js +83 -0
  202. package/lib/test/tmq/core/tmq.test.d.ts +2 -0
  203. package/lib/test/tmq/core/tmq.test.d.ts.map +1 -0
  204. package/lib/test/tmq/core/tmq.test.js +513 -0
  205. package/lib/test/tmq/failover/tmq.failover.test.d.ts +2 -0
  206. package/lib/test/tmq/failover/tmq.failover.test.d.ts.map +1 -0
  207. package/lib/test/tmq/failover/tmq.failover.test.js +404 -0
  208. package/lib/test/tmq/tmq.cloud.test.d.ts +2 -0
  209. package/lib/test/tmq/tmq.cloud.test.d.ts.map +1 -0
  210. package/lib/test/tmq/tmq.cloud.test.js +82 -0
  211. package/lib/test/tmq/tmq.config.test.d.ts +2 -0
  212. package/lib/test/tmq/tmq.config.test.d.ts.map +1 -0
  213. package/lib/test/tmq/tmq.config.test.js +94 -0
  214. package/lib/test/tmq/tmq.failover.test.d.ts +2 -0
  215. package/lib/test/tmq/tmq.failover.test.d.ts.map +1 -0
  216. package/lib/test/tmq/tmq.failover.test.js +404 -0
  217. package/lib/test/tmq/tmq.test.d.ts +2 -0
  218. package/lib/test/tmq/tmq.test.d.ts.map +1 -0
  219. package/lib/test/tmq/tmq.test.js +513 -0
  220. package/lib/test/unit/connectionManager.test.d.ts +2 -0
  221. package/lib/test/unit/connectionManager.test.d.ts.map +1 -0
  222. package/lib/test/unit/connectionManager.test.js +91 -0
  223. package/package.json +1 -1
  224. package/readme.md +2 -2
@@ -0,0 +1,338 @@
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("../helpers/utils");
7
+ const wsProxy_1 = require("../helpers/wsProxy");
8
+ function parseBinaryAction(rawData) {
9
+ if (typeof rawData === "string" || rawData.byteLength < 24) {
10
+ return null;
11
+ }
12
+ return rawData.readBigInt64LE(16);
13
+ }
14
+ describe("sql failover", () => {
15
+ jest.setTimeout(120 * 1000);
16
+ afterEach(async () => {
17
+ wsConnectorPool_1.WebSocketConnectionPool.instance().destroyed();
18
+ jest.restoreAllMocks();
19
+ });
20
+ test("switches to next address when active proxy restarts with downtime", async () => {
21
+ let restartTriggered = false;
22
+ let proxyBHadActivity = false;
23
+ let wsSql = null;
24
+ const proxyA = await wsProxy_1.WsProxy.create({
25
+ host: "127.0.0.1",
26
+ port: 0,
27
+ onEvent: (event, control) => {
28
+ if (event.type !== "message") {
29
+ return;
30
+ }
31
+ if (event.direction !== "client_to_upstream" || !event.isBinary) {
32
+ return;
33
+ }
34
+ const action = parseBinaryAction(event.rawData);
35
+ if (action === 6n && !restartTriggered) {
36
+ restartTriggered = true;
37
+ void control.restart({
38
+ downtimeMs: 800,
39
+ reason: "trigger dual-address failover",
40
+ });
41
+ }
42
+ },
43
+ });
44
+ const proxyB = await wsProxy_1.WsProxy.create({
45
+ host: "127.0.0.1",
46
+ port: 0,
47
+ onEvent: (event) => {
48
+ if (event.type === "client_connected") {
49
+ proxyBHadActivity = true;
50
+ return;
51
+ }
52
+ if (event.type === "message" &&
53
+ event.direction === "client_to_upstream") {
54
+ proxyBHadActivity = true;
55
+ }
56
+ },
57
+ });
58
+ const randomSpy = jest.spyOn(Math, "random").mockReturnValue(0);
59
+ try {
60
+ const dsn = `ws://${(0, utils_1.testUsername)()}:${(0, utils_1.testPassword)()}` +
61
+ `@127.0.0.1:${proxyA.getPort()},127.0.0.1:${proxyB.getPort()}` +
62
+ `?retries=5&retry_backoff_ms=20&retry_backoff_max_ms=20`;
63
+ const conf = new config_1.WSConfig(dsn);
64
+ conf.setTimeOut(6000);
65
+ wsSql = await wsSql_1.WsSql.open(conf);
66
+ const result = await wsSql.exec("select server_version()");
67
+ expect(result).toBeTruthy();
68
+ expect(restartTriggered).toBe(true);
69
+ expect(proxyBHadActivity).toBe(true);
70
+ }
71
+ finally {
72
+ randomSpy.mockRestore();
73
+ if (wsSql) {
74
+ await wsSql.close();
75
+ }
76
+ await proxyA.stop("test cleanup");
77
+ await proxyB.stop("test cleanup");
78
+ }
79
+ });
80
+ test("reconnects to same address after single proxy hard restart", async () => {
81
+ let restartCount = 0;
82
+ let wsSql = null;
83
+ const proxy = await wsProxy_1.WsProxy.create({
84
+ host: "127.0.0.1",
85
+ port: 0,
86
+ onEvent: (event, control) => {
87
+ if (event.type !== "message") {
88
+ return;
89
+ }
90
+ if (event.direction !== "client_to_upstream" || !event.isBinary) {
91
+ return;
92
+ }
93
+ const action = parseBinaryAction(event.rawData);
94
+ if (action === 6n && restartCount === 0) {
95
+ restartCount += 1;
96
+ void control.restart({
97
+ downtimeMs: 120,
98
+ reason: "trigger single-address reconnect",
99
+ });
100
+ }
101
+ },
102
+ });
103
+ try {
104
+ const dsn = `ws://${(0, utils_1.testUsername)()}:${(0, utils_1.testPassword)()}@127.0.0.1:${proxy.getPort()}` +
105
+ `?retries=6&retry_backoff_ms=30&retry_backoff_max_ms=60`;
106
+ const conf = new config_1.WSConfig(dsn);
107
+ conf.setTimeOut(6000);
108
+ wsSql = await wsSql_1.WsSql.open(conf);
109
+ const result = await wsSql.exec("select server_version()");
110
+ expect(result).toBeTruthy();
111
+ expect(restartCount).toBe(1);
112
+ }
113
+ finally {
114
+ if (wsSql) {
115
+ await wsSql.close();
116
+ }
117
+ await proxy.stop("test cleanup");
118
+ }
119
+ });
120
+ test("keeps all 5000 rows with single-address random proxy restarts during inserts", async () => {
121
+ const targetRows = 5000;
122
+ const baseTs = 1700000000000;
123
+ const dbName = "test_1773988174";
124
+ const tableName = "t0";
125
+ let wsSql = null;
126
+ let setupSql = null;
127
+ let cleanupSql = null;
128
+ let writePhase = false;
129
+ let restartInFlight = false;
130
+ let restartCount = 0;
131
+ let forwardedInsertFrames = 0;
132
+ const localDsn = `ws://${(0, utils_1.testUsername)()}:${(0, utils_1.testPassword)()}@127.0.0.1:6041`;
133
+ const setupConf = new config_1.WSConfig(localDsn);
134
+ setupConf.setTimeOut(6000);
135
+ setupSql = await wsSql_1.WsSql.open(setupConf);
136
+ try {
137
+ await setupSql.exec(`drop database if exists ${dbName}`);
138
+ await setupSql.exec(`create database if not exists ${dbName}`);
139
+ }
140
+ finally {
141
+ await setupSql.close();
142
+ setupSql = null;
143
+ }
144
+ const proxy = await wsProxy_1.WsProxy.create({
145
+ host: "127.0.0.1",
146
+ port: 0,
147
+ onEvent: (event, control) => {
148
+ if (!writePhase || restartInFlight) {
149
+ return;
150
+ }
151
+ if (event.type !== "message") {
152
+ return;
153
+ }
154
+ if (event.direction !== "client_to_upstream" || !event.isBinary) {
155
+ return;
156
+ }
157
+ const action = parseBinaryAction(event.rawData);
158
+ if (action !== 6n) {
159
+ return;
160
+ }
161
+ forwardedInsertFrames += 1;
162
+ if (Math.random() < 0.003) {
163
+ restartInFlight = true;
164
+ restartCount += 1;
165
+ const downtimeMs = 10 + Math.floor(Math.random() * 60);
166
+ void control.restart({
167
+ downtimeMs,
168
+ reason: `random restart #${restartCount}`,
169
+ }).finally(() => {
170
+ restartInFlight = false;
171
+ });
172
+ }
173
+ },
174
+ });
175
+ try {
176
+ const dsn = `ws://${(0, utils_1.testUsername)()}:${(0, utils_1.testPassword)()}@127.0.0.1:${proxy.getPort()}` +
177
+ `?retries=30&retry_backoff_ms=5&retry_backoff_max_ms=20`;
178
+ const conf = new config_1.WSConfig(dsn);
179
+ conf.setDb(dbName);
180
+ conf.setTimeOut(10000);
181
+ wsSql = await wsSql_1.WsSql.open(conf);
182
+ await wsSql.exec(`create table ${tableName}(ts timestamp, c1 int)`);
183
+ writePhase = true;
184
+ for (let i = 0; i < targetRows; i++) {
185
+ await wsSql.exec(`insert into ${tableName} values(${baseTs + i}, ${i})`);
186
+ }
187
+ writePhase = false;
188
+ const countResult = await wsSql.exec(`select count(*) from ${tableName}`);
189
+ const countValue = countResult.getData()?.[0]?.[0];
190
+ const rowCount = typeof countValue === "bigint"
191
+ ? Number(countValue)
192
+ : Number(countValue || 0);
193
+ expect(rowCount).toBe(targetRows);
194
+ expect(forwardedInsertFrames).toBeGreaterThanOrEqual(targetRows);
195
+ expect(restartCount).toBeGreaterThan(0);
196
+ }
197
+ finally {
198
+ writePhase = false;
199
+ if (wsSql) {
200
+ await wsSql.close();
201
+ }
202
+ await proxy.stop("test cleanup");
203
+ const cleanupConf = new config_1.WSConfig(localDsn);
204
+ cleanupConf.setTimeOut(6000);
205
+ cleanupSql = await wsSql_1.WsSql.open(cleanupConf);
206
+ try {
207
+ await cleanupSql.exec(`drop database if exists ${dbName}`);
208
+ }
209
+ finally {
210
+ await cleanupSql.close();
211
+ cleanupSql = null;
212
+ }
213
+ }
214
+ }, 300 * 1000);
215
+ test("keeps all 5000 rows with three-address random proxy restarts during inserts", async () => {
216
+ const targetRows = 5000;
217
+ const baseTs = 1700010000000;
218
+ const dbName = "test_1773989170";
219
+ const tableName = "t0";
220
+ const proxyStates = new Map();
221
+ let wsSql = null;
222
+ let setupSql = null;
223
+ let cleanupSql = null;
224
+ let writePhase = false;
225
+ const localDsn = `ws://${(0, utils_1.testUsername)()}:${(0, utils_1.testPassword)()}@127.0.0.1:6041`;
226
+ const setupConf = new config_1.WSConfig(localDsn);
227
+ setupConf.setTimeOut(6000);
228
+ setupSql = await wsSql_1.WsSql.open(setupConf);
229
+ try {
230
+ await setupSql.exec(`drop database if exists ${dbName}`);
231
+ await setupSql.exec(`create database if not exists ${dbName}`);
232
+ }
233
+ finally {
234
+ await setupSql.close();
235
+ setupSql = null;
236
+ }
237
+ const createRandomRestartProxy = async (name) => {
238
+ proxyStates.set(name, {
239
+ forwarded: 0,
240
+ restarting: false,
241
+ restarts: 0,
242
+ });
243
+ return wsProxy_1.WsProxy.create({
244
+ host: "127.0.0.1",
245
+ port: 0,
246
+ onEvent: (event, control) => {
247
+ if (!writePhase) {
248
+ return;
249
+ }
250
+ if (event.type !== "message") {
251
+ return;
252
+ }
253
+ if (event.direction !== "client_to_upstream" || !event.isBinary) {
254
+ return;
255
+ }
256
+ const action = parseBinaryAction(event.rawData);
257
+ if (action !== 6n) {
258
+ return;
259
+ }
260
+ const state = proxyStates.get(name);
261
+ if (!state) {
262
+ return;
263
+ }
264
+ state.forwarded += 1;
265
+ if (state.restarting) {
266
+ return;
267
+ }
268
+ if (Math.random() >= 0.003) {
269
+ return;
270
+ }
271
+ state.restarting = true;
272
+ state.restarts += 1;
273
+ const downtimeMs = 80 + Math.floor(Math.random() * 120);
274
+ void control
275
+ .restart({
276
+ downtimeMs,
277
+ reason: `${name} random restart #${state.restarts}`,
278
+ })
279
+ .finally(() => {
280
+ const latestState = proxyStates.get(name);
281
+ if (latestState) {
282
+ latestState.restarting = false;
283
+ }
284
+ });
285
+ },
286
+ });
287
+ };
288
+ const proxyA = await createRandomRestartProxy("proxy_a");
289
+ const proxyB = await createRandomRestartProxy("proxy_b");
290
+ const proxyC = await createRandomRestartProxy("proxy_c");
291
+ try {
292
+ const dsn = `ws://${(0, utils_1.testUsername)()}:${(0, utils_1.testPassword)()}` +
293
+ `@127.0.0.1:${proxyA.getPort()},127.0.0.1:${proxyB.getPort()},127.0.0.1:${proxyC.getPort()}` +
294
+ `?retries=24&retry_backoff_ms=8&retry_backoff_max_ms=25`;
295
+ const conf = new config_1.WSConfig(dsn);
296
+ conf.setDb(dbName);
297
+ conf.setTimeOut(10000);
298
+ wsSql = await wsSql_1.WsSql.open(conf);
299
+ await wsSql.exec(`create table ${tableName}(ts timestamp, c1 int)`);
300
+ writePhase = true;
301
+ for (let i = 0; i < targetRows; i++) {
302
+ await wsSql.exec(`insert into ${tableName} values(${baseTs + i}, ${i})`);
303
+ }
304
+ writePhase = false;
305
+ const countResult = await wsSql.exec(`select count(*) from ${tableName}`);
306
+ const countValue = countResult.getData()?.[0]?.[0];
307
+ const rowCount = typeof countValue === "bigint"
308
+ ? Number(countValue)
309
+ : Number(countValue || 0);
310
+ const totalForwarded = Array.from(proxyStates.values()).reduce((sum, state) => sum + state.forwarded, 0);
311
+ const totalRestarts = Array.from(proxyStates.values()).reduce((sum, state) => sum + state.restarts, 0);
312
+ expect(rowCount).toBe(targetRows);
313
+ expect(totalForwarded).toBeGreaterThanOrEqual(targetRows);
314
+ expect(totalRestarts).toBeGreaterThan(0);
315
+ }
316
+ finally {
317
+ writePhase = false;
318
+ if (wsSql) {
319
+ await wsSql.close();
320
+ }
321
+ await Promise.all([
322
+ proxyA.stop("test cleanup"),
323
+ proxyB.stop("test cleanup"),
324
+ proxyC.stop("test cleanup"),
325
+ ]);
326
+ const cleanupConf = new config_1.WSConfig(localDsn);
327
+ cleanupConf.setTimeOut(6000);
328
+ cleanupSql = await wsSql_1.WsSql.open(cleanupConf);
329
+ try {
330
+ await cleanupSql.exec(`drop database if exists ${dbName}`);
331
+ }
332
+ finally {
333
+ await cleanupSql.close();
334
+ cleanupSql = null;
335
+ }
336
+ }
337
+ }, 300 * 1000);
338
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stmt2.failover.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stmt2.failover.test.d.ts","sourceRoot":"","sources":["../../../test/bulkPulling/stmt2.failover.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,313 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const wsStmt2_1 = require("../../src/stmt/wsStmt2");
37
+ const wsProto = __importStar(require("../../src/stmt/wsProto"));
38
+ const Step = {
39
+ INIT: 0,
40
+ PREPARE: 1,
41
+ BIND: 2,
42
+ EXEC: 3,
43
+ RESULT: 4,
44
+ };
45
+ function createMockWsClient() {
46
+ return {
47
+ getState: jest.fn(() => 1),
48
+ connect: jest.fn(async () => { }),
49
+ checkVersion: jest.fn(async () => { }),
50
+ exec: jest.fn(async () => ({
51
+ totalTime: 0,
52
+ msg: {
53
+ code: 0,
54
+ message: "",
55
+ timing: 0,
56
+ stmt_id: 1,
57
+ is_insert: false,
58
+ fields_count: 1,
59
+ },
60
+ })),
61
+ execNoResp: jest.fn(async () => { }),
62
+ sendBinaryMsg: jest.fn(async () => ({
63
+ totalTime: 0,
64
+ msg: {
65
+ code: 0,
66
+ message: "",
67
+ timing: 0,
68
+ stmt_id: 1,
69
+ affected: 0,
70
+ },
71
+ })),
72
+ waitForReady: jest.fn(async () => { }),
73
+ isNetworkError: jest.fn((_err) => false),
74
+ };
75
+ }
76
+ function createBareStmt() {
77
+ const wsClient = createMockWsClient();
78
+ const stmt = new wsStmt2_1.WsStmt2(wsClient);
79
+ stmt._stmt_id = 1n;
80
+ return {
81
+ stmt,
82
+ wsClient,
83
+ };
84
+ }
85
+ function makeExecReady(stmt) {
86
+ const tableInfo = {
87
+ getParams: () => ({ ok: true }),
88
+ };
89
+ stmt._currentTableInfo = tableInfo;
90
+ stmt._stmtTableInfoList = [tableInfo];
91
+ stmt._toBeBindTagCount = 0;
92
+ stmt._toBeBindColCount = 0;
93
+ stmt._toBeBindTableNameIndex = undefined;
94
+ }
95
+ function makeSavedBindBytes(reqId = 0n, stmtId = 1n) {
96
+ const bytes = new ArrayBuffer(16);
97
+ const view = new DataView(bytes);
98
+ view.setBigUint64(0, reqId, true);
99
+ view.setBigUint64(8, stmtId, true);
100
+ return bytes;
101
+ }
102
+ describe("WsStmt2 failover", () => {
103
+ afterEach(() => {
104
+ jest.restoreAllMocks();
105
+ });
106
+ test("prepare caches sql and rebuilds on network error", async () => {
107
+ const { stmt, wsClient } = createBareStmt();
108
+ const networkError = new Error("socket closed");
109
+ wsClient.isNetworkError.mockReturnValue(true);
110
+ jest.spyOn(stmt, "doPrepare").mockRejectedValueOnce(networkError);
111
+ const rebuildSpy = jest
112
+ .spyOn(stmt, "rebuildContext")
113
+ .mockResolvedValue(undefined);
114
+ const sql = "select * from meters where ts > ?";
115
+ await stmt.prepare(sql);
116
+ expect(stmt._savedSql).toBe(sql);
117
+ expect(rebuildSpy).toHaveBeenCalledWith(Step.PREPARE);
118
+ });
119
+ test("exec caches bind bytes and rebuilds on network error", async () => {
120
+ const { stmt, wsClient } = createBareStmt();
121
+ const networkError = new Error("cannot call send() while not connected");
122
+ const bindBytes = new Uint8Array([1, 2, 3]).buffer;
123
+ makeExecReady(stmt);
124
+ stmt._isInsert = false;
125
+ wsClient.isNetworkError.mockReturnValue(true);
126
+ jest.spyOn(wsProto, "stmt2BinaryBlockEncode").mockReturnValue(bindBytes);
127
+ jest.spyOn(stmt, "doSendBindBytes").mockRejectedValueOnce(networkError);
128
+ jest.spyOn(stmt, "rebuildContext").mockResolvedValue(undefined);
129
+ const cleanupSpy = jest.spyOn(stmt, "cleanup");
130
+ await stmt.exec();
131
+ expect(stmt._savedBindBytes).toBe(bindBytes);
132
+ expect(stmt.rebuildContext).toHaveBeenCalledWith(Step.BIND);
133
+ expect(cleanupSpy).not.toHaveBeenCalled();
134
+ });
135
+ test("exec only cleans up immediately for insert statements", async () => {
136
+ const bindBytes = new Uint8Array([7, 8, 9]).buffer;
137
+ const insertCtx = createBareStmt();
138
+ const insertStmt = insertCtx.stmt;
139
+ makeExecReady(insertStmt);
140
+ insertStmt._isInsert = true;
141
+ jest.spyOn(wsProto, "stmt2BinaryBlockEncode").mockReturnValue(bindBytes);
142
+ jest.spyOn(insertStmt, "doSendBindBytes").mockResolvedValue(undefined);
143
+ jest.spyOn(insertStmt, "doExec").mockResolvedValue(undefined);
144
+ const insertCleanupSpy = jest.spyOn(insertStmt, "cleanup");
145
+ await insertStmt.exec();
146
+ expect(insertCleanupSpy).toHaveBeenCalledTimes(1);
147
+ const queryCtx = createBareStmt();
148
+ const queryStmt = queryCtx.stmt;
149
+ makeExecReady(queryStmt);
150
+ queryStmt._isInsert = false;
151
+ jest.spyOn(wsProto, "stmt2BinaryBlockEncode").mockReturnValue(bindBytes);
152
+ jest.spyOn(queryStmt, "doSendBindBytes").mockResolvedValue(undefined);
153
+ jest.spyOn(queryStmt, "doExec").mockResolvedValue(undefined);
154
+ const queryCleanupSpy = jest.spyOn(queryStmt, "cleanup");
155
+ await queryStmt.exec();
156
+ expect(queryCleanupSpy).not.toHaveBeenCalled();
157
+ });
158
+ test("exec cleans up insert cache even when failover rebuild fails", async () => {
159
+ const { stmt, wsClient } = createBareStmt();
160
+ const networkError = new Error("cannot call send() while not connected");
161
+ const rebuildError = new Error("rebuild failed");
162
+ const bindBytes = new Uint8Array([1, 2, 3]).buffer;
163
+ makeExecReady(stmt);
164
+ stmt._isInsert = true;
165
+ wsClient.isNetworkError.mockReturnValue(true);
166
+ jest.spyOn(wsProto, "stmt2BinaryBlockEncode").mockReturnValue(bindBytes);
167
+ jest.spyOn(stmt, "doSendBindBytes").mockRejectedValueOnce(networkError);
168
+ jest.spyOn(stmt, "rebuildContext").mockRejectedValueOnce(rebuildError);
169
+ const cleanupSpy = jest.spyOn(stmt, "cleanup");
170
+ await expect(stmt.exec()).rejects.toThrow("rebuild failed");
171
+ expect(cleanupSpy).toHaveBeenCalledTimes(1);
172
+ });
173
+ test("resultSet rebuilds on network error and cleans up", async () => {
174
+ const { stmt, wsClient } = createBareStmt();
175
+ const networkError = new Error("connection reset");
176
+ const rebuiltRows = { id: "rebuilt" };
177
+ wsClient.isNetworkError.mockReturnValue(true);
178
+ jest.spyOn(stmt, "doResult").mockRejectedValueOnce(networkError);
179
+ const rebuildSpy = jest
180
+ .spyOn(stmt, "rebuildContext")
181
+ .mockResolvedValue(rebuiltRows);
182
+ const cleanupSpy = jest.spyOn(stmt, "cleanup");
183
+ const result = await stmt.resultSet();
184
+ expect(result).toBe(rebuiltRows);
185
+ expect(rebuildSpy).toHaveBeenCalledWith(Step.RESULT);
186
+ expect(cleanupSpy).toHaveBeenCalledTimes(1);
187
+ });
188
+ test("non-network errors are rethrown without rebuild in prepare", async () => {
189
+ const { stmt, wsClient } = createBareStmt();
190
+ const nonNetworkError = new Error("invalid sql");
191
+ wsClient.isNetworkError.mockReturnValue(false);
192
+ jest.spyOn(stmt, "doPrepare").mockRejectedValueOnce(nonNetworkError);
193
+ const rebuildSpy = jest
194
+ .spyOn(stmt, "rebuildContext")
195
+ .mockResolvedValue(undefined);
196
+ await expect(stmt.prepare("bad sql")).rejects.toThrow("invalid sql");
197
+ expect(rebuildSpy).not.toHaveBeenCalled();
198
+ });
199
+ test("non-network errors are rethrown without rebuild in exec", async () => {
200
+ const { stmt, wsClient } = createBareStmt();
201
+ const bindBytes = new Uint8Array([4, 5, 6]).buffer;
202
+ const nonNetworkError = new Error("invalid bind");
203
+ makeExecReady(stmt);
204
+ stmt._isInsert = false;
205
+ wsClient.isNetworkError.mockReturnValue(false);
206
+ jest.spyOn(wsProto, "stmt2BinaryBlockEncode").mockReturnValue(bindBytes);
207
+ jest.spyOn(stmt, "doSendBindBytes").mockRejectedValueOnce(nonNetworkError);
208
+ const rebuildSpy = jest
209
+ .spyOn(stmt, "rebuildContext")
210
+ .mockResolvedValue(undefined);
211
+ await expect(stmt.exec()).rejects.toThrow("invalid bind");
212
+ expect(rebuildSpy).not.toHaveBeenCalled();
213
+ });
214
+ test("non-network errors are rethrown without rebuild in resultSet", async () => {
215
+ const { stmt, wsClient } = createBareStmt();
216
+ const nonNetworkError = new Error("result failed");
217
+ wsClient.isNetworkError.mockReturnValue(false);
218
+ jest.spyOn(stmt, "doResult").mockRejectedValueOnce(nonNetworkError);
219
+ const rebuildSpy = jest
220
+ .spyOn(stmt, "rebuildContext")
221
+ .mockResolvedValue(undefined);
222
+ await expect(stmt.resultSet()).rejects.toThrow("result failed");
223
+ expect(rebuildSpy).not.toHaveBeenCalled();
224
+ });
225
+ test("rebuildContext replays steps in order to EXEC", async () => {
226
+ const { stmt } = createBareStmt();
227
+ const callOrder = [];
228
+ stmt._savedSql = "insert into t values(?, ?)";
229
+ stmt._savedBindBytes = makeSavedBindBytes();
230
+ jest.spyOn(stmt, "doInit").mockImplementation(async () => {
231
+ callOrder.push("init");
232
+ });
233
+ jest.spyOn(stmt, "doPrepare").mockImplementation(async () => {
234
+ callOrder.push("prepare");
235
+ });
236
+ jest.spyOn(stmt, "doSendBindBytes").mockImplementation(async () => {
237
+ callOrder.push("bind");
238
+ });
239
+ jest.spyOn(stmt, "doExec").mockImplementation(async () => {
240
+ callOrder.push("exec");
241
+ });
242
+ jest.spyOn(stmt, "doResult").mockImplementation(async () => {
243
+ callOrder.push("result");
244
+ return { rows: 1 };
245
+ });
246
+ await stmt.rebuildContext(Step.EXEC);
247
+ expect(callOrder).toEqual(["init", "prepare", "bind", "exec"]);
248
+ });
249
+ test("rebuildContext can rebuild to RESULT and return rows", async () => {
250
+ const { stmt } = createBareStmt();
251
+ const rows = { data: [1, 2, 3] };
252
+ stmt._savedSql = "select * from t where ts > ?";
253
+ stmt._savedBindBytes = makeSavedBindBytes();
254
+ jest.spyOn(stmt, "doInit").mockResolvedValue(undefined);
255
+ jest.spyOn(stmt, "doPrepare").mockResolvedValue(undefined);
256
+ jest.spyOn(stmt, "doSendBindBytes").mockResolvedValue(undefined);
257
+ jest.spyOn(stmt, "doExec").mockResolvedValue(undefined);
258
+ jest.spyOn(stmt, "doResult").mockResolvedValue(rows);
259
+ const result = await stmt.rebuildContext(Step.RESULT);
260
+ expect(result).toBe(rows);
261
+ });
262
+ test("buildReplayBindBytes rewrites req_id and stmt_id", () => {
263
+ const { stmt } = createBareStmt();
264
+ const originalBytes = makeSavedBindBytes(0n, 5n);
265
+ stmt._savedBindBytes = originalBytes;
266
+ stmt._stmt_id = 42n;
267
+ const replayBytes = stmt.buildReplayBindBytes();
268
+ const originalView = new DataView(originalBytes);
269
+ const replayView = new DataView(replayBytes);
270
+ expect(replayBytes).not.toBe(originalBytes);
271
+ expect(originalView.getBigUint64(8, true)).toBe(5n);
272
+ expect(replayView.getBigUint64(8, true)).toBe(42n);
273
+ expect(replayView.getBigUint64(0, true)).not.toBe(0n);
274
+ });
275
+ test("rebuildContext retries when rebuild gets another network error", async () => {
276
+ const { stmt, wsClient } = createBareStmt();
277
+ const networkError = new Error("connection reset");
278
+ stmt._savedSql = "select * from t";
279
+ stmt._savedBindBytes = new Uint8Array([2, 4, 6]).buffer;
280
+ wsClient.isNetworkError.mockImplementation((err) => err === networkError);
281
+ const initSpy = jest
282
+ .spyOn(stmt, "doInit")
283
+ .mockRejectedValueOnce(networkError)
284
+ .mockResolvedValue(undefined);
285
+ const prepareSpy = jest.spyOn(stmt, "doPrepare").mockResolvedValue(undefined);
286
+ await stmt.rebuildContext(Step.PREPARE);
287
+ expect(initSpy).toHaveBeenCalledTimes(2);
288
+ expect(prepareSpy).toHaveBeenCalledTimes(1);
289
+ expect(wsClient.waitForReady).toHaveBeenCalledTimes(2);
290
+ });
291
+ test("rebuildContext throws after max network retry attempts", async () => {
292
+ const { stmt, wsClient } = createBareStmt();
293
+ const networkError = new Error("connection reset");
294
+ stmt._savedSql = "select * from t";
295
+ stmt._savedBindBytes = makeSavedBindBytes();
296
+ wsClient.isNetworkError.mockReturnValue(true);
297
+ const initSpy = jest
298
+ .spyOn(stmt, "doInit")
299
+ .mockRejectedValue(networkError);
300
+ await expect(stmt.rebuildContext(Step.INIT)).rejects.toThrow("connection reset");
301
+ expect(initSpy).toHaveBeenCalledTimes(3);
302
+ expect(wsClient.waitForReady).toHaveBeenCalledTimes(3);
303
+ });
304
+ test("rebuildContext throws on non-network error", async () => {
305
+ const { stmt, wsClient } = createBareStmt();
306
+ const nonNetworkError = new Error("permission denied");
307
+ stmt._savedSql = "select * from t";
308
+ stmt._savedBindBytes = new Uint8Array([9, 9, 9]).buffer;
309
+ wsClient.isNetworkError.mockReturnValue(false);
310
+ jest.spyOn(stmt, "doInit").mockRejectedValueOnce(nonNetworkError);
311
+ await expect(stmt.rebuildContext(Step.INIT)).rejects.toThrow("permission denied");
312
+ });
313
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stmt2.init.failover.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stmt2.init.failover.test.d.ts","sourceRoot":"","sources":["../../../test/bulkPulling/stmt2.init.failover.test.ts"],"names":[],"mappings":""}