@zz1996/dbhub-dameng 0.1.3 → 0.1.4
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.
|
@@ -8,6 +8,14 @@ import {
|
|
|
8
8
|
|
|
9
9
|
// src/connectors/dameng/index.ts
|
|
10
10
|
import dmdb from "dmdb";
|
|
11
|
+
var DEFAULT_OPERATION_TIMEOUT_MS = 11e4;
|
|
12
|
+
var RESOURCE_CLEANUP_TIMEOUT_MS = 2e3;
|
|
13
|
+
var DamengOperationTimeoutError = class extends Error {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = "DamengOperationTimeoutError";
|
|
17
|
+
}
|
|
18
|
+
};
|
|
11
19
|
var DamengDSNParser = class {
|
|
12
20
|
async parse(dsn, config) {
|
|
13
21
|
if (!this.isValidDSN(dsn)) {
|
|
@@ -74,6 +82,10 @@ var DamengConnector = class _DamengConnector {
|
|
|
74
82
|
this.sourceId = "default";
|
|
75
83
|
this.defaultSchema = null;
|
|
76
84
|
this.poolAlias = null;
|
|
85
|
+
this.connectionConfig = null;
|
|
86
|
+
this.connectionTimeoutMs = 5e3;
|
|
87
|
+
this.operationTimeoutMs = DEFAULT_OPERATION_TIMEOUT_MS;
|
|
88
|
+
this.reconnectingPool = null;
|
|
77
89
|
}
|
|
78
90
|
getId() {
|
|
79
91
|
return this.sourceId;
|
|
@@ -88,14 +100,22 @@ var DamengConnector = class _DamengConnector {
|
|
|
88
100
|
connectionConfig.poolAlias = this.buildPoolAlias();
|
|
89
101
|
this.defaultSchema = connectionConfig.schema ?? null;
|
|
90
102
|
this.poolAlias = connectionConfig.poolAlias;
|
|
103
|
+
this.connectionTimeoutMs = config?.connectionTimeoutSeconds !== void 0 ? config.connectionTimeoutSeconds * 1e3 : 5e3;
|
|
104
|
+
this.operationTimeoutMs = config?.queryTimeoutSeconds !== void 0 ? config.queryTimeoutSeconds * 1e3 : DEFAULT_OPERATION_TIMEOUT_MS;
|
|
91
105
|
await this.closeRegisteredPool(connectionConfig.poolAlias);
|
|
92
106
|
await this.validateDirectConnection(connectionConfig);
|
|
93
107
|
createdPool = await dmdb.createPool(connectionConfig);
|
|
94
108
|
this.pool = createdPool;
|
|
95
109
|
await this.withConnection(async (conn) => {
|
|
96
|
-
await
|
|
110
|
+
await this.executeWithTimeout(
|
|
111
|
+
conn,
|
|
112
|
+
"SELECT 1 AS OK",
|
|
113
|
+
[],
|
|
114
|
+
this.executeOptions()
|
|
115
|
+
);
|
|
97
116
|
if (!this.defaultSchema) {
|
|
98
|
-
const result = await
|
|
117
|
+
const result = await this.executeWithTimeout(
|
|
118
|
+
conn,
|
|
99
119
|
"SELECT USER AS SCHEMA_NAME FROM DUAL",
|
|
100
120
|
[],
|
|
101
121
|
this.executeOptions()
|
|
@@ -104,10 +124,17 @@ var DamengConnector = class _DamengConnector {
|
|
|
104
124
|
}
|
|
105
125
|
if (initScript) {
|
|
106
126
|
for (const statement of splitSQLStatements(initScript, "dameng")) {
|
|
107
|
-
await
|
|
127
|
+
await this.executeWithTimeout(
|
|
128
|
+
conn,
|
|
129
|
+
statement,
|
|
130
|
+
[],
|
|
131
|
+
this.executeOptions({ autoCommit: true })
|
|
132
|
+
);
|
|
108
133
|
}
|
|
109
134
|
}
|
|
110
135
|
});
|
|
136
|
+
this.connectionConfig = connectionConfig;
|
|
137
|
+
this.initScript = initScript;
|
|
111
138
|
} catch (error) {
|
|
112
139
|
if (createdPool) {
|
|
113
140
|
await this.closePoolQuietly(createdPool);
|
|
@@ -116,6 +143,8 @@ var DamengConnector = class _DamengConnector {
|
|
|
116
143
|
}
|
|
117
144
|
this.pool = null;
|
|
118
145
|
this.poolAlias = null;
|
|
146
|
+
this.connectionConfig = null;
|
|
147
|
+
this.initScript = void 0;
|
|
119
148
|
console.error("Failed to connect to Dameng database:", error);
|
|
120
149
|
throw error;
|
|
121
150
|
}
|
|
@@ -129,6 +158,9 @@ var DamengConnector = class _DamengConnector {
|
|
|
129
158
|
await this.closeRegisteredPool(this.poolAlias);
|
|
130
159
|
this.poolAlias = null;
|
|
131
160
|
}
|
|
161
|
+
this.connectionConfig = null;
|
|
162
|
+
this.initScript = void 0;
|
|
163
|
+
this.reconnectingPool = null;
|
|
132
164
|
}
|
|
133
165
|
async getSchemas() {
|
|
134
166
|
const rows = await this.queryRows(`
|
|
@@ -379,7 +411,8 @@ var DamengConnector = class _DamengConnector {
|
|
|
379
411
|
processedSQL,
|
|
380
412
|
index === 0 ? parameters ?? [] : []
|
|
381
413
|
);
|
|
382
|
-
const result = await
|
|
414
|
+
const result = await this.executeWithTimeout(
|
|
415
|
+
conn,
|
|
383
416
|
boundSQL,
|
|
384
417
|
this.toBindParams(bindValues),
|
|
385
418
|
this.executeOptions({ autoCommit: true, maxRows: options.maxRows })
|
|
@@ -393,25 +426,136 @@ var DamengConnector = class _DamengConnector {
|
|
|
393
426
|
}
|
|
394
427
|
async queryRows(sql, bindValues = []) {
|
|
395
428
|
return this.withConnection(async (conn) => {
|
|
396
|
-
const result = await
|
|
429
|
+
const result = await this.executeWithTimeout(
|
|
430
|
+
conn,
|
|
431
|
+
sql,
|
|
432
|
+
this.toBindParams(bindValues),
|
|
433
|
+
this.executeOptions()
|
|
434
|
+
);
|
|
397
435
|
return this.normalizeRows(result.rows ?? []);
|
|
398
436
|
});
|
|
399
437
|
}
|
|
400
438
|
async withConnection(fn) {
|
|
401
|
-
|
|
439
|
+
await this.ensurePool();
|
|
440
|
+
const pool = this.pool;
|
|
441
|
+
if (!pool) {
|
|
402
442
|
throw new Error("Not connected to Dameng database");
|
|
403
443
|
}
|
|
404
|
-
|
|
444
|
+
let conn = null;
|
|
445
|
+
let shouldRelease = true;
|
|
405
446
|
try {
|
|
447
|
+
conn = await this.withTimeout(
|
|
448
|
+
pool.getConnection(),
|
|
449
|
+
this.connectionTimeoutMs,
|
|
450
|
+
"Dameng connection acquisition"
|
|
451
|
+
);
|
|
406
452
|
return await fn(conn);
|
|
453
|
+
} catch (error) {
|
|
454
|
+
if (error instanceof DamengOperationTimeoutError) {
|
|
455
|
+
shouldRelease = false;
|
|
456
|
+
this.markPoolUnhealthy(error.message);
|
|
457
|
+
}
|
|
458
|
+
throw error;
|
|
459
|
+
} finally {
|
|
460
|
+
if (conn && shouldRelease) {
|
|
461
|
+
await this.releaseConnectionQuietly(conn);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
async ensurePool() {
|
|
466
|
+
if (this.pool) {
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
if (!this.connectionConfig) {
|
|
470
|
+
throw new Error("Not connected to Dameng database");
|
|
471
|
+
}
|
|
472
|
+
if (!this.reconnectingPool) {
|
|
473
|
+
this.reconnectingPool = this.reconnectPool();
|
|
474
|
+
}
|
|
475
|
+
try {
|
|
476
|
+
await this.reconnectingPool;
|
|
477
|
+
} finally {
|
|
478
|
+
this.reconnectingPool = null;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
async reconnectPool() {
|
|
482
|
+
const config = this.connectionConfig;
|
|
483
|
+
if (!config) {
|
|
484
|
+
throw new Error("Not connected to Dameng database");
|
|
485
|
+
}
|
|
486
|
+
console.error(`Reconnecting Dameng source '${this.sourceId}' after pool reset...`);
|
|
487
|
+
await this.closeRegisteredPool(config.poolAlias ?? this.buildPoolAlias());
|
|
488
|
+
await this.validateDirectConnection(config);
|
|
489
|
+
const createdPool = await dmdb.createPool(config);
|
|
490
|
+
this.pool = createdPool;
|
|
491
|
+
this.poolAlias = config.poolAlias ?? null;
|
|
492
|
+
try {
|
|
493
|
+
await this.withConnection(async (conn) => {
|
|
494
|
+
await this.executeWithTimeout(conn, "SELECT 1 AS OK", [], this.executeOptions());
|
|
495
|
+
if (this.initScript) {
|
|
496
|
+
for (const statement of splitSQLStatements(this.initScript, "dameng")) {
|
|
497
|
+
await this.executeWithTimeout(
|
|
498
|
+
conn,
|
|
499
|
+
statement,
|
|
500
|
+
[],
|
|
501
|
+
this.executeOptions({ autoCommit: true })
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
} catch (error) {
|
|
507
|
+
await this.closePoolQuietly(createdPool);
|
|
508
|
+
this.pool = null;
|
|
509
|
+
throw error;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
executeWithTimeout(conn, sql, bindParams, options) {
|
|
513
|
+
return this.withTimeout(
|
|
514
|
+
conn.execute(sql, bindParams, options),
|
|
515
|
+
this.operationTimeoutMs,
|
|
516
|
+
"Dameng SQL execution"
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
async withTimeout(promise, timeoutMs, label) {
|
|
520
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
521
|
+
return promise;
|
|
522
|
+
}
|
|
523
|
+
let timer;
|
|
524
|
+
const timeout = new Promise((_, reject) => {
|
|
525
|
+
timer = setTimeout(() => {
|
|
526
|
+
reject(new DamengOperationTimeoutError(`${label} timed out after ${timeoutMs}ms`));
|
|
527
|
+
}, timeoutMs);
|
|
528
|
+
});
|
|
529
|
+
try {
|
|
530
|
+
return await Promise.race([promise, timeout]);
|
|
407
531
|
} finally {
|
|
408
|
-
if (
|
|
409
|
-
|
|
410
|
-
} else {
|
|
411
|
-
await conn.close();
|
|
532
|
+
if (timer) {
|
|
533
|
+
clearTimeout(timer);
|
|
412
534
|
}
|
|
413
535
|
}
|
|
414
536
|
}
|
|
537
|
+
markPoolUnhealthy(reason) {
|
|
538
|
+
const pool = this.pool;
|
|
539
|
+
this.pool = null;
|
|
540
|
+
console.error(`Resetting Dameng source '${this.sourceId}' pool: ${reason}`);
|
|
541
|
+
if (pool) {
|
|
542
|
+
void this.closePoolQuietly(pool);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
async releaseConnectionQuietly(conn) {
|
|
546
|
+
try {
|
|
547
|
+
const release = conn.release ? conn.release() : conn.close();
|
|
548
|
+
await this.withTimeout(
|
|
549
|
+
release,
|
|
550
|
+
RESOURCE_CLEANUP_TIMEOUT_MS,
|
|
551
|
+
"Dameng connection release"
|
|
552
|
+
);
|
|
553
|
+
} catch (error) {
|
|
554
|
+
this.markPoolUnhealthy(
|
|
555
|
+
`failed to release connection: ${error instanceof Error ? error.message : String(error)}`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
415
559
|
executeOptions(extra = {}) {
|
|
416
560
|
return {
|
|
417
561
|
outFormat: dmdb.OUT_FORMAT_OBJECT,
|
|
@@ -430,15 +574,19 @@ var DamengConnector = class _DamengConnector {
|
|
|
430
574
|
queueTimeout,
|
|
431
575
|
...directConfig
|
|
432
576
|
} = config;
|
|
433
|
-
const directConn = await
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
577
|
+
const directConn = await this.withTimeout(
|
|
578
|
+
dmdb.getConnection({
|
|
579
|
+
...directConfig,
|
|
580
|
+
connectString: directConnectString ?? config.connectString
|
|
581
|
+
}),
|
|
582
|
+
this.connectionTimeoutMs,
|
|
583
|
+
"Dameng direct connection"
|
|
584
|
+
);
|
|
437
585
|
conn = directConn;
|
|
438
|
-
await
|
|
586
|
+
await this.executeWithTimeout(conn, "SELECT 1 AS OK", [], this.executeOptions());
|
|
439
587
|
} finally {
|
|
440
588
|
if (conn) {
|
|
441
|
-
await
|
|
589
|
+
await this.releaseConnectionQuietly(conn);
|
|
442
590
|
}
|
|
443
591
|
}
|
|
444
592
|
}
|
|
@@ -456,7 +604,7 @@ var DamengConnector = class _DamengConnector {
|
|
|
456
604
|
}
|
|
457
605
|
async closePoolQuietly(pool) {
|
|
458
606
|
try {
|
|
459
|
-
await pool.close(0);
|
|
607
|
+
await this.withTimeout(pool.close(0), RESOURCE_CLEANUP_TIMEOUT_MS, "Dameng pool close");
|
|
460
608
|
} catch {
|
|
461
609
|
if (pool.poolAlias) {
|
|
462
610
|
dmdb.pools?.delete?.(pool.poolAlias);
|
package/dist/index.js
CHANGED
|
@@ -1835,7 +1835,7 @@ var connectorModules = [
|
|
|
1835
1835
|
{ load: () => import("./sqlite-IOUAYHGE.js"), name: "SQLite", driver: "node:sqlite" },
|
|
1836
1836
|
{ load: () => import("./mysql-A43SL7UM.js"), name: "MySQL", driver: "mysql2" },
|
|
1837
1837
|
{ load: () => import("./mariadb-7F72IRB4.js"), name: "MariaDB", driver: "mariadb" },
|
|
1838
|
-
{ load: () => import("./dameng-
|
|
1838
|
+
{ load: () => import("./dameng-SOGGZUEW.js"), name: "Dameng", driver: "dmdb" }
|
|
1839
1839
|
];
|
|
1840
1840
|
loadConnectors(connectorModules).then(() => main()).catch((error) => {
|
|
1841
1841
|
console.error("Fatal error:", error);
|