@zz1996/dbhub-dameng 0.1.5 → 0.1.7
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.
|
@@ -10,9 +10,12 @@ import {
|
|
|
10
10
|
import dmdb from "dmdb";
|
|
11
11
|
var DEFAULT_OPERATION_TIMEOUT_MS = 11e4;
|
|
12
12
|
var RESOURCE_CLEANUP_TIMEOUT_MS = 2e3;
|
|
13
|
+
var CONNECT_RETRY_ATTEMPTS = 3;
|
|
14
|
+
var CONNECT_RETRY_DELAY_MS = 500;
|
|
13
15
|
var DamengOperationTimeoutError = class extends Error {
|
|
14
|
-
constructor(message) {
|
|
16
|
+
constructor(message, label) {
|
|
15
17
|
super(message);
|
|
18
|
+
this.label = label;
|
|
16
19
|
this.name = "DamengOperationTimeoutError";
|
|
17
20
|
}
|
|
18
21
|
};
|
|
@@ -94,59 +97,73 @@ var DamengConnector = class _DamengConnector {
|
|
|
94
97
|
return new _DamengConnector();
|
|
95
98
|
}
|
|
96
99
|
async connect(dsn, initScript, config) {
|
|
97
|
-
let
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
100
|
+
for (let attempt = 1; attempt <= CONNECT_RETRY_ATTEMPTS; attempt += 1) {
|
|
101
|
+
let createdPool = null;
|
|
102
|
+
try {
|
|
103
|
+
const connectionConfig = await this.dsnParser.parse(dsn, config);
|
|
104
|
+
connectionConfig.poolAlias = this.buildPoolAlias();
|
|
105
|
+
this.defaultSchema = connectionConfig.schema ?? null;
|
|
106
|
+
this.poolAlias = connectionConfig.poolAlias;
|
|
107
|
+
this.connectionTimeoutMs = config?.connectionTimeoutSeconds !== void 0 ? config.connectionTimeoutSeconds * 1e3 : 5e3;
|
|
108
|
+
this.operationTimeoutMs = config?.queryTimeoutSeconds !== void 0 ? config.queryTimeoutSeconds * 1e3 : DEFAULT_OPERATION_TIMEOUT_MS;
|
|
109
|
+
connectionConfig.connectTimeout ?? (connectionConfig.connectTimeout = this.connectionTimeoutMs);
|
|
110
|
+
connectionConfig.queueTimeout ?? (connectionConfig.queueTimeout = this.connectionTimeoutMs);
|
|
111
|
+
await this.closeRegisteredPool(connectionConfig.poolAlias);
|
|
112
|
+
await this.validateDirectConnection(connectionConfig);
|
|
113
|
+
createdPool = await dmdb.createPool(connectionConfig);
|
|
114
|
+
this.pool = createdPool;
|
|
115
|
+
await this.withConnection((conn) => this.initializeSession(conn, initScript));
|
|
116
|
+
this.connectionConfig = connectionConfig;
|
|
117
|
+
this.initScript = initScript;
|
|
118
|
+
return;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
if (createdPool) {
|
|
121
|
+
await this.closePoolQuietly(createdPool);
|
|
122
|
+
} else if (this.poolAlias) {
|
|
123
|
+
await this.closeRegisteredPool(this.poolAlias);
|
|
124
|
+
}
|
|
125
|
+
this.pool = null;
|
|
126
|
+
this.poolAlias = null;
|
|
127
|
+
this.connectionConfig = null;
|
|
128
|
+
this.initScript = void 0;
|
|
129
|
+
if (attempt < CONNECT_RETRY_ATTEMPTS && this.isRetryableConnectFailure(error)) {
|
|
130
|
+
console.error(
|
|
131
|
+
`Retrying Dameng source '${this.sourceId}' connection after transient failure (${attempt}/${CONNECT_RETRY_ATTEMPTS}): ${error instanceof Error ? error.message : String(error)}`
|
|
132
|
+
);
|
|
133
|
+
await this.delay(CONNECT_RETRY_DELAY_MS * attempt);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
console.error("Failed to connect to Dameng database:", error);
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
throw new Error("Failed to connect to Dameng database");
|
|
141
|
+
}
|
|
142
|
+
async initializeSession(conn, initScript) {
|
|
143
|
+
await this.executeWithTimeout(
|
|
144
|
+
conn,
|
|
145
|
+
"SELECT 1 AS OK",
|
|
146
|
+
[],
|
|
147
|
+
this.executeOptions()
|
|
148
|
+
);
|
|
149
|
+
if (!this.defaultSchema) {
|
|
150
|
+
const result = await this.executeWithTimeout(
|
|
151
|
+
conn,
|
|
152
|
+
"SELECT USER AS SCHEMA_NAME FROM DUAL",
|
|
153
|
+
[],
|
|
154
|
+
this.executeOptions()
|
|
155
|
+
);
|
|
156
|
+
this.defaultSchema = this.rowValue(result.rows?.[0], "SCHEMA_NAME") ?? null;
|
|
157
|
+
}
|
|
158
|
+
if (initScript) {
|
|
159
|
+
for (const statement of splitSQLStatements(initScript, "dameng")) {
|
|
110
160
|
await this.executeWithTimeout(
|
|
111
161
|
conn,
|
|
112
|
-
|
|
162
|
+
statement,
|
|
113
163
|
[],
|
|
114
|
-
this.executeOptions()
|
|
164
|
+
this.executeOptions({ autoCommit: true })
|
|
115
165
|
);
|
|
116
|
-
if (!this.defaultSchema) {
|
|
117
|
-
const result = await this.executeWithTimeout(
|
|
118
|
-
conn,
|
|
119
|
-
"SELECT USER AS SCHEMA_NAME FROM DUAL",
|
|
120
|
-
[],
|
|
121
|
-
this.executeOptions()
|
|
122
|
-
);
|
|
123
|
-
this.defaultSchema = this.rowValue(result.rows?.[0], "SCHEMA_NAME") ?? null;
|
|
124
|
-
}
|
|
125
|
-
if (initScript) {
|
|
126
|
-
for (const statement of splitSQLStatements(initScript, "dameng")) {
|
|
127
|
-
await this.executeWithTimeout(
|
|
128
|
-
conn,
|
|
129
|
-
statement,
|
|
130
|
-
[],
|
|
131
|
-
this.executeOptions({ autoCommit: true })
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
this.connectionConfig = connectionConfig;
|
|
137
|
-
this.initScript = initScript;
|
|
138
|
-
} catch (error) {
|
|
139
|
-
if (createdPool) {
|
|
140
|
-
await this.closePoolQuietly(createdPool);
|
|
141
|
-
} else if (this.poolAlias) {
|
|
142
|
-
await this.closeRegisteredPool(this.poolAlias);
|
|
143
166
|
}
|
|
144
|
-
this.pool = null;
|
|
145
|
-
this.poolAlias = null;
|
|
146
|
-
this.connectionConfig = null;
|
|
147
|
-
this.initScript = void 0;
|
|
148
|
-
console.error("Failed to connect to Dameng database:", error);
|
|
149
|
-
throw error;
|
|
150
167
|
}
|
|
151
168
|
}
|
|
152
169
|
async disconnect() {
|
|
@@ -494,6 +511,20 @@ var DamengConnector = class _DamengConnector {
|
|
|
494
511
|
});
|
|
495
512
|
}
|
|
496
513
|
async withConnection(fn) {
|
|
514
|
+
try {
|
|
515
|
+
return await this.withConnectionAttempt(fn);
|
|
516
|
+
} catch (error) {
|
|
517
|
+
if (!this.isConnectionAcquisitionFailure(error)) {
|
|
518
|
+
throw error;
|
|
519
|
+
}
|
|
520
|
+
console.error(
|
|
521
|
+
`Retrying Dameng source '${this.sourceId}' after connection acquisition failure: ${error instanceof Error ? error.message : String(error)}`
|
|
522
|
+
);
|
|
523
|
+
await this.ensurePool();
|
|
524
|
+
return this.withConnectionAttempt(fn);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
async withConnectionAttempt(fn) {
|
|
497
528
|
await this.ensurePool();
|
|
498
529
|
const pool = this.pool;
|
|
499
530
|
if (!pool) {
|
|
@@ -502,16 +533,15 @@ var DamengConnector = class _DamengConnector {
|
|
|
502
533
|
let conn = null;
|
|
503
534
|
let shouldRelease = true;
|
|
504
535
|
try {
|
|
505
|
-
conn = await this.
|
|
506
|
-
pool.getConnection(),
|
|
507
|
-
this.connectionTimeoutMs,
|
|
508
|
-
"Dameng connection acquisition"
|
|
509
|
-
);
|
|
536
|
+
conn = await this.acquireConnectionWithTimeout(pool);
|
|
510
537
|
return await fn(conn);
|
|
511
538
|
} catch (error) {
|
|
512
539
|
if (error instanceof DamengOperationTimeoutError) {
|
|
513
540
|
shouldRelease = false;
|
|
514
541
|
this.markPoolUnhealthy(error.message);
|
|
542
|
+
} else if (!conn && this.isConnectionAcquisitionFailure(error)) {
|
|
543
|
+
shouldRelease = false;
|
|
544
|
+
this.markPoolUnhealthy(error instanceof Error ? error.message : String(error));
|
|
515
545
|
}
|
|
516
546
|
throw error;
|
|
517
547
|
} finally {
|
|
@@ -520,6 +550,21 @@ var DamengConnector = class _DamengConnector {
|
|
|
520
550
|
}
|
|
521
551
|
}
|
|
522
552
|
}
|
|
553
|
+
async acquireConnectionWithTimeout(pool) {
|
|
554
|
+
const acquisition = pool.getConnection();
|
|
555
|
+
try {
|
|
556
|
+
return await this.withTimeout(
|
|
557
|
+
acquisition,
|
|
558
|
+
this.connectionTimeoutMs,
|
|
559
|
+
"Dameng connection acquisition"
|
|
560
|
+
);
|
|
561
|
+
} catch (error) {
|
|
562
|
+
if (error instanceof DamengOperationTimeoutError) {
|
|
563
|
+
void acquisition.then((conn) => this.releaseConnectionQuietly(conn)).catch(() => void 0);
|
|
564
|
+
}
|
|
565
|
+
throw error;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
523
568
|
async ensurePool() {
|
|
524
569
|
if (this.pool) {
|
|
525
570
|
return;
|
|
@@ -581,7 +626,7 @@ var DamengConnector = class _DamengConnector {
|
|
|
581
626
|
let timer;
|
|
582
627
|
const timeout = new Promise((_, reject) => {
|
|
583
628
|
timer = setTimeout(() => {
|
|
584
|
-
reject(new DamengOperationTimeoutError(`${label} timed out after ${timeoutMs}ms
|
|
629
|
+
reject(new DamengOperationTimeoutError(`${label} timed out after ${timeoutMs}ms`, label));
|
|
585
630
|
}, timeoutMs);
|
|
586
631
|
});
|
|
587
632
|
try {
|
|
@@ -614,6 +659,46 @@ var DamengConnector = class _DamengConnector {
|
|
|
614
659
|
);
|
|
615
660
|
}
|
|
616
661
|
}
|
|
662
|
+
isConnectionAcquisitionFailure(error) {
|
|
663
|
+
if (error instanceof DamengOperationTimeoutError) {
|
|
664
|
+
return error.label === "Dameng connection acquisition";
|
|
665
|
+
}
|
|
666
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
667
|
+
return [
|
|
668
|
+
"Connection request timeout in queue",
|
|
669
|
+
"Pool cannot open more connections",
|
|
670
|
+
"\u83B7\u53D6\u8FDE\u63A5\u8BF7\u6C42\u7B49\u5F85\u8D85\u65F6",
|
|
671
|
+
"\u8FDE\u63A5\u6C60\u5DF2\u8FBE\u5230\u6700\u5927\u8FDE\u63A5\u6570"
|
|
672
|
+
].some((item) => message.includes(item));
|
|
673
|
+
}
|
|
674
|
+
isRetryableConnectFailure(error) {
|
|
675
|
+
if (error instanceof DamengOperationTimeoutError) {
|
|
676
|
+
return [
|
|
677
|
+
"Dameng direct connection",
|
|
678
|
+
"Dameng connection acquisition",
|
|
679
|
+
"Dameng SQL execution"
|
|
680
|
+
].includes(error.label);
|
|
681
|
+
}
|
|
682
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
683
|
+
return [
|
|
684
|
+
"ECONNRESET",
|
|
685
|
+
"ETIMEDOUT",
|
|
686
|
+
"ECONNREFUSED",
|
|
687
|
+
"socket hang up",
|
|
688
|
+
"Socket timeout",
|
|
689
|
+
"connect timeout",
|
|
690
|
+
"Connection request timeout in queue",
|
|
691
|
+
"Pool cannot open more connections",
|
|
692
|
+
"\u7F51\u7EDC\u901A\u8BAF\u8D85\u65F6",
|
|
693
|
+
"\u7F51\u7EDC\u901A\u4FE1\u5F02\u5E38",
|
|
694
|
+
"\u8FDE\u63A5\u8D85\u65F6",
|
|
695
|
+
"\u83B7\u53D6\u8FDE\u63A5\u8BF7\u6C42\u7B49\u5F85\u8D85\u65F6",
|
|
696
|
+
"\u8FDE\u63A5\u6C60\u5DF2\u8FBE\u5230\u6700\u5927\u8FDE\u63A5\u6570"
|
|
697
|
+
].some((item) => message.includes(item));
|
|
698
|
+
}
|
|
699
|
+
delay(ms) {
|
|
700
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
701
|
+
}
|
|
617
702
|
executeOptions(extra = {}) {
|
|
618
703
|
return {
|
|
619
704
|
outFormat: dmdb.OUT_FORMAT_OBJECT,
|
package/dist/index.js
CHANGED
|
@@ -1865,7 +1865,7 @@ var connectorModules = [
|
|
|
1865
1865
|
{ load: () => import("./sqlite-IOUAYHGE.js"), name: "SQLite", driver: "node:sqlite" },
|
|
1866
1866
|
{ load: () => import("./mysql-A43SL7UM.js"), name: "MySQL", driver: "mysql2" },
|
|
1867
1867
|
{ load: () => import("./mariadb-7F72IRB4.js"), name: "MariaDB", driver: "mariadb" },
|
|
1868
|
-
{ load: () => import("./dameng-
|
|
1868
|
+
{ load: () => import("./dameng-5KYI5JBK.js"), name: "Dameng", driver: "dmdb" }
|
|
1869
1869
|
];
|
|
1870
1870
|
loadConnectors(connectorModules).then(() => main()).catch((error) => {
|
|
1871
1871
|
console.error("Fatal error:", error);
|