relq 1.0.111 → 1.0.113
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/dist/cjs/core/pg-family/shared/pg-base.cjs +36 -8
- package/dist/cjs/core/relq-base.cjs +16 -3
- package/dist/cjs/errors/relq-errors.cjs +17 -1
- package/dist/esm/core/pg-family/shared/pg-base.js +36 -8
- package/dist/esm/core/relq-base.js +16 -3
- package/dist/esm/errors/relq-errors.js +17 -1
- package/dist/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -257,15 +257,24 @@ class PgBase extends relq_base_1.RelqBase {
|
|
|
257
257
|
return;
|
|
258
258
|
this.poolErrorHandler = (err) => {
|
|
259
259
|
const errorCode = err.code;
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
260
|
+
if (isPoolRecoverableError(errorCode)) {
|
|
261
|
+
const logLevel = this.config.logLevel ?? 'info';
|
|
262
|
+
if (logLevel !== 'silent') {
|
|
263
|
+
console.warn('[Relq Pool] Recoverable connection error (pool will auto-recover):', {
|
|
264
|
+
code: errorCode,
|
|
265
|
+
message: err.message,
|
|
266
|
+
action: 'Connection removed from pool, will be replaced on next query'
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const logLevel = this.config.logLevel ?? 'info';
|
|
272
|
+
if (logLevel !== 'silent') {
|
|
273
|
+
console.error('[Relq Pool] Pool error:', {
|
|
274
|
+
code: errorCode,
|
|
275
|
+
message: err.message,
|
|
276
|
+
});
|
|
263
277
|
}
|
|
264
|
-
console.warn('[Relq Pool] Recoverable connection error (pool will auto-recover):', {
|
|
265
|
-
code: errorCode,
|
|
266
|
-
message: err.message,
|
|
267
|
-
action: 'Connection removed from pool, will be replaced on next query'
|
|
268
|
-
});
|
|
269
278
|
};
|
|
270
279
|
this.poolConnectHandler = () => { };
|
|
271
280
|
this.poolRemoveHandler = () => { };
|
|
@@ -349,3 +358,22 @@ class PgBase extends relq_base_1.RelqBase {
|
|
|
349
358
|
}
|
|
350
359
|
}
|
|
351
360
|
exports.PgBase = PgBase;
|
|
361
|
+
const POOL_RECOVERABLE_NETWORK_CODES = new Set([
|
|
362
|
+
'ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ESERVFAIL',
|
|
363
|
+
'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN', 'EHOSTUNREACH',
|
|
364
|
+
'ECONNABORTED', 'ENETUNREACH', 'ENETRESET',
|
|
365
|
+
'CONNECTION_LOST', 'PROTOCOL_CONNECTION_LOST',
|
|
366
|
+
]);
|
|
367
|
+
const POOL_RECOVERABLE_PG_CODES = new Set([
|
|
368
|
+
'57P01',
|
|
369
|
+
'57P02',
|
|
370
|
+
'57P03',
|
|
371
|
+
'08006',
|
|
372
|
+
'08001',
|
|
373
|
+
'08004',
|
|
374
|
+
]);
|
|
375
|
+
function isPoolRecoverableError(code) {
|
|
376
|
+
if (!code)
|
|
377
|
+
return true;
|
|
378
|
+
return POOL_RECOVERABLE_NETWORK_CODES.has(code) || POOL_RECOVERABLE_PG_CODES.has(code);
|
|
379
|
+
}
|
|
@@ -14,6 +14,7 @@ class RelqBase {
|
|
|
14
14
|
config;
|
|
15
15
|
schema;
|
|
16
16
|
emitter = new node_events_1.EventEmitter();
|
|
17
|
+
_defaultErrorHandler = () => { };
|
|
17
18
|
columnMappings = new Map();
|
|
18
19
|
initialized = false;
|
|
19
20
|
initPromise;
|
|
@@ -21,6 +22,7 @@ class RelqBase {
|
|
|
21
22
|
constructor(schema, config) {
|
|
22
23
|
this.config = config;
|
|
23
24
|
this.schema = schema;
|
|
25
|
+
this.emitter.on('error', this._defaultErrorHandler);
|
|
24
26
|
if (schema) {
|
|
25
27
|
const log = config.logLevel === 'debug'
|
|
26
28
|
? (...args) => (0, helpers_1.debugLog)(config, ...args)
|
|
@@ -243,15 +245,26 @@ class RelqBase {
|
|
|
243
245
|
}
|
|
244
246
|
}
|
|
245
247
|
exports.RelqBase = RelqBase;
|
|
246
|
-
const
|
|
248
|
+
const TRANSIENT_NETWORK_CODES = new Set([
|
|
247
249
|
'ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ESERVFAIL',
|
|
248
250
|
'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN', 'EHOSTUNREACH',
|
|
249
251
|
'CONNECTION_LOST', 'PROTOCOL_CONNECTION_LOST',
|
|
250
252
|
]);
|
|
253
|
+
const TRANSIENT_PG_CODES = new Set([
|
|
254
|
+
'40P01',
|
|
255
|
+
'40001',
|
|
256
|
+
'08006',
|
|
257
|
+
'08001',
|
|
258
|
+
'08004',
|
|
259
|
+
'57P01',
|
|
260
|
+
'57P03',
|
|
261
|
+
]);
|
|
251
262
|
function isTransientError(error) {
|
|
252
|
-
if (
|
|
263
|
+
if (TRANSIENT_NETWORK_CODES.has(error.code))
|
|
264
|
+
return true;
|
|
265
|
+
if (error.cause && TRANSIENT_NETWORK_CODES.has(error.cause.code))
|
|
253
266
|
return true;
|
|
254
|
-
if (
|
|
267
|
+
if (TRANSIENT_PG_CODES.has(error.code))
|
|
255
268
|
return true;
|
|
256
269
|
return false;
|
|
257
270
|
}
|
|
@@ -312,7 +312,15 @@ function wrapError(error, context) {
|
|
|
312
312
|
function parsePostgresError(error, sql) {
|
|
313
313
|
const message = error.message || 'Database error';
|
|
314
314
|
const code = error.code;
|
|
315
|
-
if (code
|
|
315
|
+
if (isNetworkErrorCode(code)) {
|
|
316
|
+
return new RelqConnectionError(message, {
|
|
317
|
+
cause: error,
|
|
318
|
+
code,
|
|
319
|
+
host: error.hostname || error.address,
|
|
320
|
+
port: error.port
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
if (code === '57P01' || code === '57P03' || code === '08006' || code === '08001' || code === '08004') {
|
|
316
324
|
return new RelqConnectionError(message, {
|
|
317
325
|
cause: error,
|
|
318
326
|
code,
|
|
@@ -331,3 +339,11 @@ function parsePostgresError(error, sql) {
|
|
|
331
339
|
hint: error.hint
|
|
332
340
|
});
|
|
333
341
|
}
|
|
342
|
+
const NETWORK_ERROR_CODES = new Set([
|
|
343
|
+
'ECONNREFUSED', 'ECONNRESET', 'ENOTFOUND', 'ESERVFAIL',
|
|
344
|
+
'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN', 'EHOSTUNREACH',
|
|
345
|
+
'CONNECTION_LOST', 'PROTOCOL_CONNECTION_LOST',
|
|
346
|
+
]);
|
|
347
|
+
function isNetworkErrorCode(code) {
|
|
348
|
+
return !!code && NETWORK_ERROR_CODES.has(code);
|
|
349
|
+
}
|
|
@@ -220,15 +220,24 @@ export class PgBase extends RelqBase {
|
|
|
220
220
|
return;
|
|
221
221
|
this.poolErrorHandler = (err) => {
|
|
222
222
|
const errorCode = err.code;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
223
|
+
if (isPoolRecoverableError(errorCode)) {
|
|
224
|
+
const logLevel = this.config.logLevel ?? 'info';
|
|
225
|
+
if (logLevel !== 'silent') {
|
|
226
|
+
console.warn('[Relq Pool] Recoverable connection error (pool will auto-recover):', {
|
|
227
|
+
code: errorCode,
|
|
228
|
+
message: err.message,
|
|
229
|
+
action: 'Connection removed from pool, will be replaced on next query'
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const logLevel = this.config.logLevel ?? 'info';
|
|
235
|
+
if (logLevel !== 'silent') {
|
|
236
|
+
console.error('[Relq Pool] Pool error:', {
|
|
237
|
+
code: errorCode,
|
|
238
|
+
message: err.message,
|
|
239
|
+
});
|
|
226
240
|
}
|
|
227
|
-
console.warn('[Relq Pool] Recoverable connection error (pool will auto-recover):', {
|
|
228
|
-
code: errorCode,
|
|
229
|
-
message: err.message,
|
|
230
|
-
action: 'Connection removed from pool, will be replaced on next query'
|
|
231
|
-
});
|
|
232
241
|
};
|
|
233
242
|
this.poolConnectHandler = () => { };
|
|
234
243
|
this.poolRemoveHandler = () => { };
|
|
@@ -311,3 +320,22 @@ export class PgBase extends RelqBase {
|
|
|
311
320
|
this.emitter.emit('connect', this.client);
|
|
312
321
|
}
|
|
313
322
|
}
|
|
323
|
+
const POOL_RECOVERABLE_NETWORK_CODES = new Set([
|
|
324
|
+
'ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ESERVFAIL',
|
|
325
|
+
'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN', 'EHOSTUNREACH',
|
|
326
|
+
'ECONNABORTED', 'ENETUNREACH', 'ENETRESET',
|
|
327
|
+
'CONNECTION_LOST', 'PROTOCOL_CONNECTION_LOST',
|
|
328
|
+
]);
|
|
329
|
+
const POOL_RECOVERABLE_PG_CODES = new Set([
|
|
330
|
+
'57P01',
|
|
331
|
+
'57P02',
|
|
332
|
+
'57P03',
|
|
333
|
+
'08006',
|
|
334
|
+
'08001',
|
|
335
|
+
'08004',
|
|
336
|
+
]);
|
|
337
|
+
function isPoolRecoverableError(code) {
|
|
338
|
+
if (!code)
|
|
339
|
+
return true;
|
|
340
|
+
return POOL_RECOVERABLE_NETWORK_CODES.has(code) || POOL_RECOVERABLE_PG_CODES.has(code);
|
|
341
|
+
}
|
|
@@ -11,6 +11,7 @@ export class RelqBase {
|
|
|
11
11
|
config;
|
|
12
12
|
schema;
|
|
13
13
|
emitter = new EventEmitter();
|
|
14
|
+
_defaultErrorHandler = () => { };
|
|
14
15
|
columnMappings = new Map();
|
|
15
16
|
initialized = false;
|
|
16
17
|
initPromise;
|
|
@@ -18,6 +19,7 @@ export class RelqBase {
|
|
|
18
19
|
constructor(schema, config) {
|
|
19
20
|
this.config = config;
|
|
20
21
|
this.schema = schema;
|
|
22
|
+
this.emitter.on('error', this._defaultErrorHandler);
|
|
21
23
|
if (schema) {
|
|
22
24
|
const log = config.logLevel === 'debug'
|
|
23
25
|
? (...args) => debugLog(config, ...args)
|
|
@@ -239,15 +241,26 @@ export class RelqBase {
|
|
|
239
241
|
return this._isClosed;
|
|
240
242
|
}
|
|
241
243
|
}
|
|
242
|
-
const
|
|
244
|
+
const TRANSIENT_NETWORK_CODES = new Set([
|
|
243
245
|
'ECONNRESET', 'ECONNREFUSED', 'ENOTFOUND', 'ESERVFAIL',
|
|
244
246
|
'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN', 'EHOSTUNREACH',
|
|
245
247
|
'CONNECTION_LOST', 'PROTOCOL_CONNECTION_LOST',
|
|
246
248
|
]);
|
|
249
|
+
const TRANSIENT_PG_CODES = new Set([
|
|
250
|
+
'40P01',
|
|
251
|
+
'40001',
|
|
252
|
+
'08006',
|
|
253
|
+
'08001',
|
|
254
|
+
'08004',
|
|
255
|
+
'57P01',
|
|
256
|
+
'57P03',
|
|
257
|
+
]);
|
|
247
258
|
function isTransientError(error) {
|
|
248
|
-
if (
|
|
259
|
+
if (TRANSIENT_NETWORK_CODES.has(error.code))
|
|
260
|
+
return true;
|
|
261
|
+
if (error.cause && TRANSIENT_NETWORK_CODES.has(error.cause.code))
|
|
249
262
|
return true;
|
|
250
|
-
if (
|
|
263
|
+
if (TRANSIENT_PG_CODES.has(error.code))
|
|
251
264
|
return true;
|
|
252
265
|
return false;
|
|
253
266
|
}
|
|
@@ -290,7 +290,15 @@ export function wrapError(error, context) {
|
|
|
290
290
|
export function parsePostgresError(error, sql) {
|
|
291
291
|
const message = error.message || 'Database error';
|
|
292
292
|
const code = error.code;
|
|
293
|
-
if (code
|
|
293
|
+
if (isNetworkErrorCode(code)) {
|
|
294
|
+
return new RelqConnectionError(message, {
|
|
295
|
+
cause: error,
|
|
296
|
+
code,
|
|
297
|
+
host: error.hostname || error.address,
|
|
298
|
+
port: error.port
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
if (code === '57P01' || code === '57P03' || code === '08006' || code === '08001' || code === '08004') {
|
|
294
302
|
return new RelqConnectionError(message, {
|
|
295
303
|
cause: error,
|
|
296
304
|
code,
|
|
@@ -309,3 +317,11 @@ export function parsePostgresError(error, sql) {
|
|
|
309
317
|
hint: error.hint
|
|
310
318
|
});
|
|
311
319
|
}
|
|
320
|
+
const NETWORK_ERROR_CODES = new Set([
|
|
321
|
+
'ECONNREFUSED', 'ECONNRESET', 'ENOTFOUND', 'ESERVFAIL',
|
|
322
|
+
'ETIMEDOUT', 'EPIPE', 'EAI_AGAIN', 'EHOSTUNREACH',
|
|
323
|
+
'CONNECTION_LOST', 'PROTOCOL_CONNECTION_LOST',
|
|
324
|
+
]);
|
|
325
|
+
function isNetworkErrorCode(code) {
|
|
326
|
+
return !!code && NETWORK_ERROR_CODES.has(code);
|
|
327
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -10023,6 +10023,7 @@ export declare abstract class RelqBase<TSchema = any> {
|
|
|
10023
10023
|
protected config: RelqConfig;
|
|
10024
10024
|
protected schema?: TSchema;
|
|
10025
10025
|
protected readonly emitter: EventEmitter<any>;
|
|
10026
|
+
private readonly _defaultErrorHandler;
|
|
10026
10027
|
protected columnMappings: ColumnMappings;
|
|
10027
10028
|
protected initialized: boolean;
|
|
10028
10029
|
protected initPromise?: Promise<void>;
|