pg-cache 1.6.8 → 1.6.9
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/esm/pg.js +54 -0
- package/package.json +2 -2
- package/pg.js +54 -0
package/esm/pg.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import pg from 'pg';
|
|
2
2
|
import { getPgEnvOptions } from 'pg-env';
|
|
3
|
+
import { Logger } from '@pgpmjs/logger';
|
|
3
4
|
import { pgCache } from './lru';
|
|
5
|
+
const log = new Logger('pg-cache');
|
|
4
6
|
const getDbString = (user, password, host, port, database) => `postgres://${user}:${password}@${host}:${port}/${database}`;
|
|
5
7
|
export const getPgPool = (pgConfig) => {
|
|
6
8
|
const config = getPgEnvOptions(pgConfig);
|
|
@@ -12,6 +14,58 @@ export const getPgPool = (pgConfig) => {
|
|
|
12
14
|
}
|
|
13
15
|
const connectionString = getDbString(user, password, host, port, database);
|
|
14
16
|
const pgPool = new pg.Pool({ connectionString });
|
|
17
|
+
/**
|
|
18
|
+
* IMPORTANT: Pool-level error handler for idle connection errors.
|
|
19
|
+
*
|
|
20
|
+
* WHY THIS EXISTS:
|
|
21
|
+
* pg-pool maintains a pool of database connections. When a connection is idle
|
|
22
|
+
* (not actively running a query) and the server terminates it (e.g., during
|
|
23
|
+
* database cleanup via pg_terminate_backend), pg-pool emits an 'error' event
|
|
24
|
+
* on the pool's EventEmitter. In Node.js, an EventEmitter 'error' event with
|
|
25
|
+
* no listeners is FATAL and crashes the entire process with an unhelpful
|
|
26
|
+
* stack trace showing internal pg-pool/pg-protocol objects.
|
|
27
|
+
*
|
|
28
|
+
* WHY THIS IS SAFE (does NOT swallow real errors):
|
|
29
|
+
* This handler ONLY catches errors emitted on IDLE pooled connections via
|
|
30
|
+
* the EventEmitter pattern. It does NOT intercept errors from active queries.
|
|
31
|
+
*
|
|
32
|
+
* Error paths in pg-pool:
|
|
33
|
+
* 1. QUERY ERRORS (pool.query(), client.query()):
|
|
34
|
+
* - Returned via Promise rejection
|
|
35
|
+
* - Bubble up through async/await as normal exceptions
|
|
36
|
+
* - NOT affected by this handler - they still throw as expected
|
|
37
|
+
* - Examples: syntax errors, constraint violations, connection refused
|
|
38
|
+
*
|
|
39
|
+
* 2. IDLE CONNECTION ERRORS (this handler):
|
|
40
|
+
* - Emitted via EventEmitter when server kills an idle connection
|
|
41
|
+
* - Without a handler: crashes Node.js process
|
|
42
|
+
* - With this handler: logged and process continues
|
|
43
|
+
* - Examples: pg_terminate_backend during cleanup, server restart
|
|
44
|
+
*
|
|
45
|
+
* WHEN THIS FIRES:
|
|
46
|
+
* - pgpm test-packages creates temp databases, deploys, then drops them
|
|
47
|
+
* - Dropping requires pg_terminate_backend() to kill active connections
|
|
48
|
+
* - Idle connections in the pool receive PostgreSQL error 57P01
|
|
49
|
+
* - This handler catches that expected cleanup error
|
|
50
|
+
*
|
|
51
|
+
* PostgreSQL error codes handled:
|
|
52
|
+
* - 57P01: admin_shutdown (terminating connection due to administrator command)
|
|
53
|
+
* This is EXPECTED during database teardown and logged at debug level.
|
|
54
|
+
*
|
|
55
|
+
* All other error codes are logged at error level for visibility but do not
|
|
56
|
+
* crash the process, allowing the test harness to continue and report results.
|
|
57
|
+
*/
|
|
58
|
+
pgPool.on('error', (err) => {
|
|
59
|
+
if (err.code === '57P01') {
|
|
60
|
+
// Expected during database cleanup - log at debug level
|
|
61
|
+
log.debug(`Pool ${database} connection terminated (expected during cleanup): ${err.message}`);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Unexpected pool error - log at error level for visibility
|
|
65
|
+
// Note: This does NOT swallow query errors - those still throw via Promise rejection
|
|
66
|
+
log.error(`Pool ${database} unexpected idle connection error [${err.code || 'unknown'}]: ${err.message}`);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
15
69
|
pgCache.set(database, pgPool);
|
|
16
70
|
return pgPool;
|
|
17
71
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pg-cache",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.9",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "PostgreSQL connection pool LRU cache manager",
|
|
6
6
|
"main": "index.js",
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
"connection",
|
|
49
49
|
"constructive"
|
|
50
50
|
],
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "fc182ff9e4c4745a3e86eda6d58e3b0061f36564"
|
|
52
52
|
}
|
package/pg.js
CHANGED
|
@@ -6,7 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.getPgPool = void 0;
|
|
7
7
|
const pg_1 = __importDefault(require("pg"));
|
|
8
8
|
const pg_env_1 = require("pg-env");
|
|
9
|
+
const logger_1 = require("@pgpmjs/logger");
|
|
9
10
|
const lru_1 = require("./lru");
|
|
11
|
+
const log = new logger_1.Logger('pg-cache');
|
|
10
12
|
const getDbString = (user, password, host, port, database) => `postgres://${user}:${password}@${host}:${port}/${database}`;
|
|
11
13
|
const getPgPool = (pgConfig) => {
|
|
12
14
|
const config = (0, pg_env_1.getPgEnvOptions)(pgConfig);
|
|
@@ -18,6 +20,58 @@ const getPgPool = (pgConfig) => {
|
|
|
18
20
|
}
|
|
19
21
|
const connectionString = getDbString(user, password, host, port, database);
|
|
20
22
|
const pgPool = new pg_1.default.Pool({ connectionString });
|
|
23
|
+
/**
|
|
24
|
+
* IMPORTANT: Pool-level error handler for idle connection errors.
|
|
25
|
+
*
|
|
26
|
+
* WHY THIS EXISTS:
|
|
27
|
+
* pg-pool maintains a pool of database connections. When a connection is idle
|
|
28
|
+
* (not actively running a query) and the server terminates it (e.g., during
|
|
29
|
+
* database cleanup via pg_terminate_backend), pg-pool emits an 'error' event
|
|
30
|
+
* on the pool's EventEmitter. In Node.js, an EventEmitter 'error' event with
|
|
31
|
+
* no listeners is FATAL and crashes the entire process with an unhelpful
|
|
32
|
+
* stack trace showing internal pg-pool/pg-protocol objects.
|
|
33
|
+
*
|
|
34
|
+
* WHY THIS IS SAFE (does NOT swallow real errors):
|
|
35
|
+
* This handler ONLY catches errors emitted on IDLE pooled connections via
|
|
36
|
+
* the EventEmitter pattern. It does NOT intercept errors from active queries.
|
|
37
|
+
*
|
|
38
|
+
* Error paths in pg-pool:
|
|
39
|
+
* 1. QUERY ERRORS (pool.query(), client.query()):
|
|
40
|
+
* - Returned via Promise rejection
|
|
41
|
+
* - Bubble up through async/await as normal exceptions
|
|
42
|
+
* - NOT affected by this handler - they still throw as expected
|
|
43
|
+
* - Examples: syntax errors, constraint violations, connection refused
|
|
44
|
+
*
|
|
45
|
+
* 2. IDLE CONNECTION ERRORS (this handler):
|
|
46
|
+
* - Emitted via EventEmitter when server kills an idle connection
|
|
47
|
+
* - Without a handler: crashes Node.js process
|
|
48
|
+
* - With this handler: logged and process continues
|
|
49
|
+
* - Examples: pg_terminate_backend during cleanup, server restart
|
|
50
|
+
*
|
|
51
|
+
* WHEN THIS FIRES:
|
|
52
|
+
* - pgpm test-packages creates temp databases, deploys, then drops them
|
|
53
|
+
* - Dropping requires pg_terminate_backend() to kill active connections
|
|
54
|
+
* - Idle connections in the pool receive PostgreSQL error 57P01
|
|
55
|
+
* - This handler catches that expected cleanup error
|
|
56
|
+
*
|
|
57
|
+
* PostgreSQL error codes handled:
|
|
58
|
+
* - 57P01: admin_shutdown (terminating connection due to administrator command)
|
|
59
|
+
* This is EXPECTED during database teardown and logged at debug level.
|
|
60
|
+
*
|
|
61
|
+
* All other error codes are logged at error level for visibility but do not
|
|
62
|
+
* crash the process, allowing the test harness to continue and report results.
|
|
63
|
+
*/
|
|
64
|
+
pgPool.on('error', (err) => {
|
|
65
|
+
if (err.code === '57P01') {
|
|
66
|
+
// Expected during database cleanup - log at debug level
|
|
67
|
+
log.debug(`Pool ${database} connection terminated (expected during cleanup): ${err.message}`);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// Unexpected pool error - log at error level for visibility
|
|
71
|
+
// Note: This does NOT swallow query errors - those still throw via Promise rejection
|
|
72
|
+
log.error(`Pool ${database} unexpected idle connection error [${err.code || 'unknown'}]: ${err.message}`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
21
75
|
lru_1.pgCache.set(database, pgPool);
|
|
22
76
|
return pgPool;
|
|
23
77
|
};
|