@juit/pgproxy-pool 1.0.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.
- package/README.md +8 -0
- package/dist/connection.cjs +309 -0
- package/dist/connection.cjs.map +6 -0
- package/dist/connection.d.ts +112 -0
- package/dist/connection.mjs +273 -0
- package/dist/connection.mjs.map +6 -0
- package/dist/events.cjs +56 -0
- package/dist/events.cjs.map +6 -0
- package/dist/events.d.ts +16 -0
- package/dist/events.mjs +31 -0
- package/dist/events.mjs.map +6 -0
- package/dist/index.cjs +34 -0
- package/dist/index.cjs.map +6 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.mjs +8 -0
- package/dist/index.mjs.map +6 -0
- package/dist/libpq.cjs +32 -0
- package/dist/libpq.cjs.map +6 -0
- package/dist/libpq.d.ts +6 -0
- package/dist/libpq.mjs +7 -0
- package/dist/libpq.mjs.map +6 -0
- package/dist/pool.cjs +486 -0
- package/dist/pool.cjs.map +6 -0
- package/dist/pool.d.ts +159 -0
- package/dist/pool.mjs +451 -0
- package/dist/pool.mjs.map +6 -0
- package/dist/queue.cjs +70 -0
- package/dist/queue.cjs.map +6 -0
- package/dist/queue.d.ts +7 -0
- package/dist/queue.mjs +45 -0
- package/dist/queue.mjs.map +6 -0
- package/package.json +47 -0
- package/src/connection.ts +494 -0
- package/src/events.ts +42 -0
- package/src/index.ts +17 -0
- package/src/libpq.ts +10 -0
- package/src/pool.ts +683 -0
- package/src/queue.ts +47 -0
package/dist/pool.cjs
ADDED
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// pool.ts
|
|
31
|
+
var pool_exports = {};
|
|
32
|
+
__export(pool_exports, {
|
|
33
|
+
ConnectionPool: () => ConnectionPool
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(pool_exports);
|
|
36
|
+
var import_node_assert = __toESM(require("node:assert"));
|
|
37
|
+
var import_connection = require("./connection.cjs");
|
|
38
|
+
var import_events = require("./events.cjs");
|
|
39
|
+
function parseEnvNumber(variable, defaultValue) {
|
|
40
|
+
const string = process.env[variable];
|
|
41
|
+
if (string == null)
|
|
42
|
+
return defaultValue;
|
|
43
|
+
const value = parseFloat(string);
|
|
44
|
+
if (isNaN(value))
|
|
45
|
+
throw new Error(`Invalid value "${string}" for environment variable "${variable}"`);
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
function parseEnvBoolean(variable, defaultValue) {
|
|
49
|
+
const string = process.env[variable];
|
|
50
|
+
if (string == null)
|
|
51
|
+
return defaultValue;
|
|
52
|
+
const value = string.toLowerCase();
|
|
53
|
+
if (value === "false")
|
|
54
|
+
return false;
|
|
55
|
+
if (value === "true")
|
|
56
|
+
return true;
|
|
57
|
+
throw new Error(`Invalid value "${string}" for environment variable "${variable}"`);
|
|
58
|
+
}
|
|
59
|
+
var ConnectionRequest = class {
|
|
60
|
+
_resolve;
|
|
61
|
+
_reject;
|
|
62
|
+
_promise;
|
|
63
|
+
_timeout;
|
|
64
|
+
_pending = true;
|
|
65
|
+
/**
|
|
66
|
+
* Create a new {@link ConnectionRequest} with a timeout, after which the
|
|
67
|
+
* request will be automatically rejected.
|
|
68
|
+
*/
|
|
69
|
+
constructor(timeout) {
|
|
70
|
+
this._promise = new Promise((resolve, reject) => {
|
|
71
|
+
this._resolve = resolve;
|
|
72
|
+
this._reject = reject;
|
|
73
|
+
});
|
|
74
|
+
this._timeout = setTimeout(() => {
|
|
75
|
+
this.reject(new Error(`Timeout of ${timeout} ms reached acquiring connection`));
|
|
76
|
+
}, timeout).unref();
|
|
77
|
+
}
|
|
78
|
+
/** Return the {@link Promise} to the {@link Connection} */
|
|
79
|
+
get promise() {
|
|
80
|
+
return this._promise;
|
|
81
|
+
}
|
|
82
|
+
/** Determine whether this request is still pending or not */
|
|
83
|
+
get pending() {
|
|
84
|
+
return this._pending;
|
|
85
|
+
}
|
|
86
|
+
/** Resolve this instance's {@link Promise} with a {@link Connection} */
|
|
87
|
+
resolve(connection) {
|
|
88
|
+
clearTimeout(this._timeout);
|
|
89
|
+
if (this._pending)
|
|
90
|
+
this._resolve(connection);
|
|
91
|
+
this._pending = false;
|
|
92
|
+
}
|
|
93
|
+
/** Reject this instance's {@link Promise} with an {@link Error} */
|
|
94
|
+
reject(error) {
|
|
95
|
+
clearTimeout(this._timeout);
|
|
96
|
+
if (this._pending)
|
|
97
|
+
this._reject(error);
|
|
98
|
+
this._pending = false;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
var ConnectionPool = class extends import_events.Emitter {
|
|
102
|
+
/** Borrowed connections mapped to their borrow timeout */
|
|
103
|
+
_borrowed = /* @__PURE__ */ new Map();
|
|
104
|
+
/** Array of all _available_ connections (that is, not borrowed out) */
|
|
105
|
+
_available = [];
|
|
106
|
+
/** Array of all pending {@link ConnectionRequest}s */
|
|
107
|
+
_pending = [];
|
|
108
|
+
/** All connections mapped to their evictor callback handler */
|
|
109
|
+
_connections = /* @__PURE__ */ new Map();
|
|
110
|
+
/** A {@link WeakMap} of connections already evicted by this pool */
|
|
111
|
+
_evicted = /* @__PURE__ */ new WeakSet();
|
|
112
|
+
/** The minimum number of connections to keep in the pool */
|
|
113
|
+
_minimumPoolSize;
|
|
114
|
+
/** The maximum number of connections to keep in the pool */
|
|
115
|
+
_maximumPoolSize;
|
|
116
|
+
/** The maximum number of idle connections that can be sitting in the pool */
|
|
117
|
+
_maximumIdleConnections;
|
|
118
|
+
/** The number of *milliseconds* after which an `acquire()` call will fail */
|
|
119
|
+
_acquireTimeoutMs;
|
|
120
|
+
/** The maximum number of *milliseconds* a connection can be borrowed for */
|
|
121
|
+
_borrowTimeoutMs;
|
|
122
|
+
/** The number of *milliseconds* to wait after the creation of a connection failed */
|
|
123
|
+
_retryIntervalMs;
|
|
124
|
+
/** Whether to validate connections on borrow or not */
|
|
125
|
+
_validateOnBorrow;
|
|
126
|
+
/** The {@link ConnectionOptions} converted into a string for `LibPQ` */
|
|
127
|
+
_connectionOptions;
|
|
128
|
+
/** Indicator on whether this {@link ConnectionPool} was started or not */
|
|
129
|
+
_started = false;
|
|
130
|
+
/** Indicator on whether this {@link ConnectionPool} is starting or not */
|
|
131
|
+
_starting = false;
|
|
132
|
+
constructor(logger, options = {}) {
|
|
133
|
+
super(logger);
|
|
134
|
+
const {
|
|
135
|
+
minimumPoolSize = parseEnvNumber("PGPOOLMINSIZE", 0),
|
|
136
|
+
maximumPoolSize = parseEnvNumber("PGPOOLMAXSIZE", minimumPoolSize + 20),
|
|
137
|
+
maximumIdleConnections = parseEnvNumber("PGPOOLIDLECONN", (maximumPoolSize + minimumPoolSize) / 2),
|
|
138
|
+
acquireTimeout = parseEnvNumber("PGPOOLACQUIRETIMEOUT", 30),
|
|
139
|
+
borrowTimeout = parseEnvNumber("PGPOOLBORROWTIMEOUT", 120),
|
|
140
|
+
retryInterval = parseEnvNumber("PGPOOLRETRYINTERVAL", 5),
|
|
141
|
+
validateOnBorrow = parseEnvBoolean("PGPOOLVALIDATEONBORROW", true),
|
|
142
|
+
...connectionOptions
|
|
143
|
+
} = options;
|
|
144
|
+
this._minimumPoolSize = Math.round(minimumPoolSize);
|
|
145
|
+
this._maximumPoolSize = Math.round(maximumPoolSize);
|
|
146
|
+
this._maximumIdleConnections = Math.ceil(maximumIdleConnections);
|
|
147
|
+
this._acquireTimeoutMs = Math.round(acquireTimeout * 1e3);
|
|
148
|
+
this._borrowTimeoutMs = Math.round(borrowTimeout * 1e3);
|
|
149
|
+
this._retryIntervalMs = Math.round(retryInterval * 1e3);
|
|
150
|
+
this._validateOnBorrow = validateOnBorrow;
|
|
151
|
+
(0, import_node_assert.default)(this._minimumPoolSize >= 0, `Invalid minimum pool size: ${this._minimumPoolSize}`);
|
|
152
|
+
(0, import_node_assert.default)(this._maximumPoolSize >= 1, `Invalid maximum pool size: ${this._maximumPoolSize}`);
|
|
153
|
+
(0, import_node_assert.default)(this._maximumIdleConnections >= 0, `Invalid maximum idle connections: ${this._maximumIdleConnections}`);
|
|
154
|
+
(0, import_node_assert.default)(this._acquireTimeoutMs > 0, `Invalid acquire timeout: ${this._acquireTimeoutMs} ms`);
|
|
155
|
+
(0, import_node_assert.default)(this._borrowTimeoutMs > 0, `Invalid borrow timeout: ${this._borrowTimeoutMs} ms`);
|
|
156
|
+
(0, import_node_assert.default)(this._retryIntervalMs > 0, `Invalid retry interval: ${this._retryIntervalMs} ms`);
|
|
157
|
+
(0, import_node_assert.default)(
|
|
158
|
+
this._minimumPoolSize <= this._maximumPoolSize,
|
|
159
|
+
`The minimum pool size ${this._minimumPoolSize} must less or equal to the maximum pool size ${this._maximumPoolSize}`
|
|
160
|
+
);
|
|
161
|
+
(0, import_node_assert.default)(
|
|
162
|
+
this._minimumPoolSize <= this._maximumIdleConnections,
|
|
163
|
+
`The minimum pool size ${this._minimumPoolSize} must less or equal to the maximum number of idle connections ${this._maximumIdleConnections}`
|
|
164
|
+
);
|
|
165
|
+
(0, import_node_assert.default)(
|
|
166
|
+
this._maximumIdleConnections <= this._maximumPoolSize,
|
|
167
|
+
`The maximum number of idle connections ${this._maximumIdleConnections} must less or equal to the maximum pool size ${this._maximumPoolSize}`
|
|
168
|
+
);
|
|
169
|
+
this._connectionOptions = (0, import_connection.convertOptions)(connectionOptions);
|
|
170
|
+
this._logger = logger;
|
|
171
|
+
}
|
|
172
|
+
/** Statistical informations about a {@link ConnectionPool} */
|
|
173
|
+
get stats() {
|
|
174
|
+
const available = this._available.length;
|
|
175
|
+
const borrowed = this._borrowed.size;
|
|
176
|
+
const total = this._connections.size;
|
|
177
|
+
const connecting = total - (available + borrowed);
|
|
178
|
+
return { available, borrowed, connecting, total };
|
|
179
|
+
}
|
|
180
|
+
/** Returns a flag indicating whether this pool is running or not */
|
|
181
|
+
get running() {
|
|
182
|
+
return this._started || this._starting;
|
|
183
|
+
}
|
|
184
|
+
/** Returns the running configuration of this instance */
|
|
185
|
+
get configuration() {
|
|
186
|
+
return {
|
|
187
|
+
minimumPoolSize: this._minimumPoolSize,
|
|
188
|
+
maximumPoolSize: this._maximumPoolSize,
|
|
189
|
+
maximumIdleConnections: this._maximumIdleConnections,
|
|
190
|
+
acquireTimeout: this._acquireTimeoutMs / 1e3,
|
|
191
|
+
borrowTimeout: this._borrowTimeoutMs / 1e3,
|
|
192
|
+
retryInterval: this._retryIntervalMs / 1e3,
|
|
193
|
+
validateOnBorrow: this._validateOnBorrow
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/* ===== CONNECTION MANAGEMENT ============================================ */
|
|
197
|
+
/* These methods are protected, as they can be overridden to provide more
|
|
198
|
+
* specialized versions of connections */
|
|
199
|
+
/** Create a connection */
|
|
200
|
+
_create(logger, params) {
|
|
201
|
+
return new import_connection.Connection(logger, params);
|
|
202
|
+
}
|
|
203
|
+
/** Validate a connection by issuing a super-simple statement */
|
|
204
|
+
async _validate(connection) {
|
|
205
|
+
if (!connection.connected)
|
|
206
|
+
return false;
|
|
207
|
+
if (!this._validateOnBorrow)
|
|
208
|
+
return true;
|
|
209
|
+
const start = process.hrtime.bigint();
|
|
210
|
+
try {
|
|
211
|
+
this._logger.debug(`Validating connection "${connection.id}"`);
|
|
212
|
+
const result = await connection.query("SELECT now()");
|
|
213
|
+
return result.rowCount === 1;
|
|
214
|
+
} catch (error) {
|
|
215
|
+
this._logger.error(`Error validating connection "${connection.id}":`, error);
|
|
216
|
+
return false;
|
|
217
|
+
} finally {
|
|
218
|
+
const time = process.hrtime.bigint() - start;
|
|
219
|
+
const ms = Math.floor(Number(time) / 1e4) / 100;
|
|
220
|
+
this._logger.debug(`Connection "${connection.id}" validated in ${ms} ms`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/** Recycle a connection rolling back any running transaction */
|
|
224
|
+
async _recycle(connection) {
|
|
225
|
+
if (!connection.connected)
|
|
226
|
+
return false;
|
|
227
|
+
try {
|
|
228
|
+
const result = await connection.query("SELECT pg_current_xact_id_if_assigned() IS NOT NULL");
|
|
229
|
+
if (result.rows[0]?.[0] === "t") {
|
|
230
|
+
this._logger.warn(`Rolling back transaction recycling connection "${connection.id}"`);
|
|
231
|
+
await connection.query("ROLLBACK");
|
|
232
|
+
}
|
|
233
|
+
return true;
|
|
234
|
+
} catch (error) {
|
|
235
|
+
this._logger.error(`Error recycling connection "${connection.id}":`, error);
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/* ===== CONNECTION / POOL INTERACTION ==================================== */
|
|
240
|
+
/** Adopt a connection tying it to our events */
|
|
241
|
+
_adopt(connection) {
|
|
242
|
+
const destroyer = () => {
|
|
243
|
+
connection.off("destroyed", evictor);
|
|
244
|
+
this._evict(connection);
|
|
245
|
+
};
|
|
246
|
+
this.once("stopped", destroyer);
|
|
247
|
+
const evictor = (forced) => {
|
|
248
|
+
this.off("stopped", destroyer);
|
|
249
|
+
if (forced)
|
|
250
|
+
return;
|
|
251
|
+
this._evict(connection);
|
|
252
|
+
this._runCreateLoop();
|
|
253
|
+
};
|
|
254
|
+
connection.once("destroyed", evictor);
|
|
255
|
+
this._connections.set(connection, evictor);
|
|
256
|
+
return connection;
|
|
257
|
+
}
|
|
258
|
+
/** Destroy a connection, it will be wiped from this pool */
|
|
259
|
+
_evict(connection, aborted = false) {
|
|
260
|
+
const evictor = this._connections.get(connection);
|
|
261
|
+
if (!evictor) {
|
|
262
|
+
this._logger.warn(`Attempting to evict non adopted connection ${connection.id}`);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
this._connections.delete(connection);
|
|
266
|
+
connection.off("destroyed", evictor);
|
|
267
|
+
evictor(true);
|
|
268
|
+
try {
|
|
269
|
+
this._logger.debug(`Destroying connection "${connection.id}"`);
|
|
270
|
+
clearTimeout(this._borrowed.get(connection));
|
|
271
|
+
this._borrowed.delete(connection);
|
|
272
|
+
const index = this._available.indexOf(connection);
|
|
273
|
+
if (index >= 0)
|
|
274
|
+
this._available.splice(index);
|
|
275
|
+
connection.destroy();
|
|
276
|
+
this._emit(aborted ? "connection_aborted" : "connection_destroyed", connection);
|
|
277
|
+
} catch (error) {
|
|
278
|
+
this._logger.error(`Error destroying connection "${connection.id}"`);
|
|
279
|
+
} finally {
|
|
280
|
+
this._evicted.add(connection);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/* ===== RUN LOOPS ======================================================== */
|
|
284
|
+
/**
|
|
285
|
+
* Run the create connection loop.
|
|
286
|
+
*
|
|
287
|
+
* This loop simply creates connections, connects them, sets up the various
|
|
288
|
+
* event handler (on disconnect) and simply adds them to the available array.
|
|
289
|
+
*/
|
|
290
|
+
_runCreateLoop() {
|
|
291
|
+
if (!this._started)
|
|
292
|
+
return;
|
|
293
|
+
Promise.resolve().then(async () => {
|
|
294
|
+
while (this._started) {
|
|
295
|
+
const connections = this._connections.size;
|
|
296
|
+
const available = this._available.length;
|
|
297
|
+
const pending = this._pending.length;
|
|
298
|
+
if (available && connections >= this._minimumPoolSize || // enough available for minimum pool size
|
|
299
|
+
!pending && available >= this._maximumIdleConnections || // enough maximum idle connections
|
|
300
|
+
connections >= this._maximumPoolSize) {
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
let connection;
|
|
304
|
+
try {
|
|
305
|
+
connection = this._create(this._logger, this._connectionOptions);
|
|
306
|
+
this._adopt(connection);
|
|
307
|
+
} catch (error) {
|
|
308
|
+
const retry = `retrying in ${this._retryIntervalMs} ms`;
|
|
309
|
+
this._logger.error(`Error creating pooled connection, ${retry}:`, error);
|
|
310
|
+
await new Promise((resolve) => setTimeout(resolve, this._retryIntervalMs));
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
await connection.connect();
|
|
315
|
+
} catch (error) {
|
|
316
|
+
const retry = `retrying in ${this._retryIntervalMs} ms`;
|
|
317
|
+
this._logger.error(`Error connecting "${connection.id}", ${retry}:`, error);
|
|
318
|
+
this._evict(connection, true);
|
|
319
|
+
await new Promise((resolve) => setTimeout(resolve, this._retryIntervalMs));
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
if (this._started)
|
|
323
|
+
this._available.push(connection);
|
|
324
|
+
else
|
|
325
|
+
this._evict(connection, true);
|
|
326
|
+
this._runBorrowLoop();
|
|
327
|
+
this._emit("connection_created", connection);
|
|
328
|
+
}
|
|
329
|
+
}).catch(
|
|
330
|
+
/* coverage ignore next */
|
|
331
|
+
(error) => {
|
|
332
|
+
const retry = `retrying in ${this._retryIntervalMs} ms`;
|
|
333
|
+
this._logger.error(`Error in create loop, ${retry}:`, error);
|
|
334
|
+
setTimeout(() => this._runCreateLoop(), this._retryIntervalMs);
|
|
335
|
+
}
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Run the borrow connection loop.
|
|
340
|
+
*
|
|
341
|
+
* This loop looks at all the pending connection requests, and fullfills them
|
|
342
|
+
* with a connection from the available array. If no connections are available
|
|
343
|
+
* then it simply triggers the create loop.
|
|
344
|
+
*/
|
|
345
|
+
_runBorrowLoop() {
|
|
346
|
+
if (!this._started)
|
|
347
|
+
return;
|
|
348
|
+
Promise.resolve().then(async () => {
|
|
349
|
+
let request;
|
|
350
|
+
while (this._started && (request = this._pending.splice(0, 1)[0])) {
|
|
351
|
+
const connection = this._available.splice(0, 1)[0];
|
|
352
|
+
if (!connection) {
|
|
353
|
+
if (request.pending)
|
|
354
|
+
this._pending.unshift(request);
|
|
355
|
+
return this._runCreateLoop();
|
|
356
|
+
}
|
|
357
|
+
if (!request.pending) {
|
|
358
|
+
if (this._available.length >= this._maximumIdleConnections) {
|
|
359
|
+
this._evict(connection);
|
|
360
|
+
} else {
|
|
361
|
+
this._available.push(connection);
|
|
362
|
+
}
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
const valid = await this._validate(connection);
|
|
366
|
+
if (!this._started) {
|
|
367
|
+
request.reject(new Error(`Pool stopped while validatin connection ${connection.id}`));
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (!valid) {
|
|
371
|
+
if (request.pending)
|
|
372
|
+
this._pending.unshift(request);
|
|
373
|
+
this._evict(connection);
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (!request.pending) {
|
|
377
|
+
this.release(connection);
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
const timeout = setTimeout(() => {
|
|
381
|
+
this._logger.error(`Connection "${connection.id}" borrowed for too long`);
|
|
382
|
+
this._evict(connection);
|
|
383
|
+
}, this._borrowTimeoutMs).unref();
|
|
384
|
+
this._borrowed.set(connection, timeout);
|
|
385
|
+
this._emit("connection_acquired", connection);
|
|
386
|
+
request.resolve(connection);
|
|
387
|
+
}
|
|
388
|
+
}).catch(
|
|
389
|
+
/* coverage ignore next */
|
|
390
|
+
(error) => {
|
|
391
|
+
const retry = `retrying in ${this._retryIntervalMs} ms`;
|
|
392
|
+
this._logger.error(`Error in borrow loop, ${retry}:`, error);
|
|
393
|
+
setTimeout(() => this._runBorrowLoop(), this._retryIntervalMs);
|
|
394
|
+
}
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
/* ===== CONNECTION LIFECYCLE ============================================= */
|
|
398
|
+
/** Acquire a {@link Connection} from this {@link ConnectionPool} */
|
|
399
|
+
acquire() {
|
|
400
|
+
(0, import_node_assert.default)(this._started, "Connection pool not started");
|
|
401
|
+
const deferred = new ConnectionRequest(this._acquireTimeoutMs);
|
|
402
|
+
this._pending.push(deferred);
|
|
403
|
+
this._runBorrowLoop();
|
|
404
|
+
return deferred.promise;
|
|
405
|
+
}
|
|
406
|
+
/** Release a {@link Connection} back to this {@link ConnectionPool} */
|
|
407
|
+
release(connection) {
|
|
408
|
+
if (this._evicted.has(connection))
|
|
409
|
+
return;
|
|
410
|
+
(0, import_node_assert.default)(this._connections.has(connection), `Connection "${connection.id}" not owned by this pool`);
|
|
411
|
+
Promise.resolve().then(async () => {
|
|
412
|
+
this._logger.debug(`Releasing connection "${connection.id}"`);
|
|
413
|
+
clearTimeout(this._borrowed.get(connection));
|
|
414
|
+
if (!connection.connected) {
|
|
415
|
+
this._logger.info(`Disconnected connection "${connection.id}" discarded`);
|
|
416
|
+
this._evict(connection);
|
|
417
|
+
} else if (this._available.length >= this._maximumIdleConnections) {
|
|
418
|
+
this._logger.info(`Extra connection "${connection.id}" discarded`);
|
|
419
|
+
this._evict(connection);
|
|
420
|
+
} else if (!await this._recycle(connection)) {
|
|
421
|
+
this._logger.info(`Non-validated connection "${connection.id}" discarded`);
|
|
422
|
+
this._evict(connection);
|
|
423
|
+
} else {
|
|
424
|
+
this._logger.debug(`Connection "${connection.id}" released`);
|
|
425
|
+
this._borrowed.delete(connection);
|
|
426
|
+
this._available.push(connection);
|
|
427
|
+
this._emit("connection_released", connection);
|
|
428
|
+
}
|
|
429
|
+
}).catch((error) => {
|
|
430
|
+
this._logger.error(`Error releasing connection "${connection.id}":`, error);
|
|
431
|
+
this._evict(connection);
|
|
432
|
+
}).finally(() => this._runBorrowLoop());
|
|
433
|
+
}
|
|
434
|
+
/* ===== POOL LIFECYCLE =================================================== */
|
|
435
|
+
/** Start this {@link ConnectionPool} validating an initial connection */
|
|
436
|
+
async start() {
|
|
437
|
+
if (this._started || this._starting)
|
|
438
|
+
return this;
|
|
439
|
+
this._logger.debug("Starting connection pool");
|
|
440
|
+
this._starting = true;
|
|
441
|
+
try {
|
|
442
|
+
const connection = this._create(this._logger, this._connectionOptions);
|
|
443
|
+
await connection.connect();
|
|
444
|
+
const valid = await this._validate(connection);
|
|
445
|
+
(0, import_node_assert.default)(valid, `Unable to validate initial connection "${connection.id}"`);
|
|
446
|
+
this._logger.debug(`Initial connection "${connection.id}" validated`);
|
|
447
|
+
this._adopt(connection);
|
|
448
|
+
this._started = true;
|
|
449
|
+
this._emit("started");
|
|
450
|
+
this._emit("connection_created", connection);
|
|
451
|
+
if (this._maximumIdleConnections > 0) {
|
|
452
|
+
this._available.push(connection);
|
|
453
|
+
} else {
|
|
454
|
+
this._evict(connection);
|
|
455
|
+
}
|
|
456
|
+
this._runCreateLoop();
|
|
457
|
+
return this;
|
|
458
|
+
} finally {
|
|
459
|
+
this._starting = false;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
/** Stop this {@link ConnectionPool} and disconnect all connections. */
|
|
463
|
+
stop() {
|
|
464
|
+
if (!this._started)
|
|
465
|
+
return;
|
|
466
|
+
this._started = false;
|
|
467
|
+
const connections = `${this._connections.size} connections`;
|
|
468
|
+
const requests = `${this._pending.length} pending requests`;
|
|
469
|
+
this._logger.info(`Stopping connection pool with ${connections} and ${requests}`);
|
|
470
|
+
for (const pending of this._pending) {
|
|
471
|
+
pending.reject(new Error("Connection pool stopped"));
|
|
472
|
+
}
|
|
473
|
+
this._available.splice(0, Number.MAX_SAFE_INTEGER);
|
|
474
|
+
this._borrowed.clear();
|
|
475
|
+
try {
|
|
476
|
+
this._emit("stopped");
|
|
477
|
+
} finally {
|
|
478
|
+
this._connections.clear();
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
483
|
+
0 && (module.exports = {
|
|
484
|
+
ConnectionPool
|
|
485
|
+
});
|
|
486
|
+
//# sourceMappingURL=pool.cjs.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/pool.ts"],
|
|
4
|
+
"mappings": "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",
|
|
5
|
+
"names": ["assert"]
|
|
6
|
+
}
|
package/dist/pool.d.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { Connection } from './connection';
|
|
2
|
+
import { Emitter } from './events';
|
|
3
|
+
import type { ConnectionOptions } from './connection';
|
|
4
|
+
import type { Logger } from './index';
|
|
5
|
+
/** Configuration for our {@link ConnectionPool}. */
|
|
6
|
+
export interface ConnectionPoolConfig {
|
|
7
|
+
/**
|
|
8
|
+
* The minimum number of connections to keep in the pool
|
|
9
|
+
*
|
|
10
|
+
* * _default_: `0`
|
|
11
|
+
* * _environment varaible_: `PGPOOLMINSIZE`
|
|
12
|
+
*/
|
|
13
|
+
minimumPoolSize?: number;
|
|
14
|
+
/**
|
|
15
|
+
* The maximum number of connections to keep in the pool
|
|
16
|
+
*
|
|
17
|
+
* * _default_: `20` more than `minimumPoolSize`
|
|
18
|
+
* * _environment varaible_: `PGPOOLMAXSIZE`
|
|
19
|
+
*/
|
|
20
|
+
maximumPoolSize?: number;
|
|
21
|
+
/**
|
|
22
|
+
* The maximum number of idle connections that can be sitting in the pool.
|
|
23
|
+
*
|
|
24
|
+
* * _default_: the average between `minimumPoolSize` and `maximumPoolSize`
|
|
25
|
+
* * _environment varaible_: `PGPOOLIDLECONN`
|
|
26
|
+
*/
|
|
27
|
+
maximumIdleConnections?: number;
|
|
28
|
+
/**
|
|
29
|
+
* The number of seconds after which an `acquire()` call will fail
|
|
30
|
+
*
|
|
31
|
+
* * _default_: `30` sec.
|
|
32
|
+
* * _environment varaible_: `PGPOOLACQUIRETIMEOUT`
|
|
33
|
+
*/
|
|
34
|
+
acquireTimeout?: number;
|
|
35
|
+
/**
|
|
36
|
+
* The maximum number of seconds a connection can be borrowed for
|
|
37
|
+
*
|
|
38
|
+
* * _default_: `120` sec.
|
|
39
|
+
* * _environment varaible_: `PGPOOLBORROWTIMEOUT`
|
|
40
|
+
*/
|
|
41
|
+
borrowTimeout?: number;
|
|
42
|
+
/**
|
|
43
|
+
* The number of seconds to wait after the creation of a connection failed
|
|
44
|
+
*
|
|
45
|
+
* * _default_: `5` sec.
|
|
46
|
+
* * _environment varaible_: `PGPOOLRETRYINTERVAL`
|
|
47
|
+
*/
|
|
48
|
+
retryInterval?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Whether to validate connections on borrow or not
|
|
51
|
+
*
|
|
52
|
+
* * _default_: `true`.
|
|
53
|
+
* * _environment varaible_: `PGPOOLVALIDATEONBORROW`
|
|
54
|
+
*/
|
|
55
|
+
validateOnBorrow?: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** Constructor options for our {@link ConnectionPool} */
|
|
58
|
+
export interface ConnectionPoolOptions extends ConnectionPoolConfig, ConnectionOptions {
|
|
59
|
+
}
|
|
60
|
+
/** Statistical informations about a {@link ConnectionPool} */
|
|
61
|
+
export interface ConnectionPoolStats {
|
|
62
|
+
/** The number of {@link Connection}s currently available in the pool */
|
|
63
|
+
available: number;
|
|
64
|
+
/** The number of {@link Connection}s currently borrowed out by the pool */
|
|
65
|
+
borrowed: number;
|
|
66
|
+
/** The number of {@link Connection}s currently connecting */
|
|
67
|
+
connecting: number;
|
|
68
|
+
/** The total number of {@link Connection}s managed by the pool */
|
|
69
|
+
total: number;
|
|
70
|
+
}
|
|
71
|
+
/** Events generated by our {@link ConnectionPool} */
|
|
72
|
+
interface ConnectionPoolEvents {
|
|
73
|
+
started: () => unknown;
|
|
74
|
+
stopped: () => unknown;
|
|
75
|
+
/** Emitted after the connection has been created, connected and adopted */
|
|
76
|
+
connection_created: (connection: Connection) => unknown;
|
|
77
|
+
/** Emitted after the connection has been evicted and destroyed */
|
|
78
|
+
connection_destroyed: (connection: Connection) => unknown;
|
|
79
|
+
/** Emitted when a created connection can not be connected */
|
|
80
|
+
connection_aborted: (connection: Connection) => unknown;
|
|
81
|
+
/** Emitted when a connection has been acquired */
|
|
82
|
+
connection_acquired: (connection: Connection) => unknown;
|
|
83
|
+
/** Emitted when a connection has been released */
|
|
84
|
+
connection_released: (connection: Connection) => unknown;
|
|
85
|
+
}
|
|
86
|
+
export declare class ConnectionPool extends Emitter<ConnectionPoolEvents> {
|
|
87
|
+
/** Borrowed connections mapped to their borrow timeout */
|
|
88
|
+
private readonly _borrowed;
|
|
89
|
+
/** Array of all _available_ connections (that is, not borrowed out) */
|
|
90
|
+
private readonly _available;
|
|
91
|
+
/** Array of all pending {@link ConnectionRequest}s */
|
|
92
|
+
private readonly _pending;
|
|
93
|
+
/** All connections mapped to their evictor callback handler */
|
|
94
|
+
private readonly _connections;
|
|
95
|
+
/** A {@link WeakMap} of connections already evicted by this pool */
|
|
96
|
+
private readonly _evicted;
|
|
97
|
+
/** The minimum number of connections to keep in the pool */
|
|
98
|
+
private readonly _minimumPoolSize;
|
|
99
|
+
/** The maximum number of connections to keep in the pool */
|
|
100
|
+
private readonly _maximumPoolSize;
|
|
101
|
+
/** The maximum number of idle connections that can be sitting in the pool */
|
|
102
|
+
private readonly _maximumIdleConnections;
|
|
103
|
+
/** The number of *milliseconds* after which an `acquire()` call will fail */
|
|
104
|
+
private readonly _acquireTimeoutMs;
|
|
105
|
+
/** The maximum number of *milliseconds* a connection can be borrowed for */
|
|
106
|
+
private readonly _borrowTimeoutMs;
|
|
107
|
+
/** The number of *milliseconds* to wait after the creation of a connection failed */
|
|
108
|
+
private readonly _retryIntervalMs;
|
|
109
|
+
/** Whether to validate connections on borrow or not */
|
|
110
|
+
private readonly _validateOnBorrow;
|
|
111
|
+
/** The {@link ConnectionOptions} converted into a string for `LibPQ` */
|
|
112
|
+
private readonly _connectionOptions;
|
|
113
|
+
/** Indicator on whether this {@link ConnectionPool} was started or not */
|
|
114
|
+
private _started;
|
|
115
|
+
/** Indicator on whether this {@link ConnectionPool} is starting or not */
|
|
116
|
+
private _starting;
|
|
117
|
+
/** Create a new {@link ConnectionPool} */
|
|
118
|
+
constructor(logger: Logger, options?: ConnectionPoolOptions);
|
|
119
|
+
/** Statistical informations about a {@link ConnectionPool} */
|
|
120
|
+
get stats(): ConnectionPoolStats;
|
|
121
|
+
/** Returns a flag indicating whether this pool is running or not */
|
|
122
|
+
get running(): boolean;
|
|
123
|
+
/** Returns the running configuration of this instance */
|
|
124
|
+
get configuration(): Required<ConnectionPoolConfig>;
|
|
125
|
+
/** Create a connection */
|
|
126
|
+
protected _create(logger: Logger, params: string): Connection;
|
|
127
|
+
/** Validate a connection by issuing a super-simple statement */
|
|
128
|
+
protected _validate(connection: Connection): Promise<boolean>;
|
|
129
|
+
/** Recycle a connection rolling back any running transaction */
|
|
130
|
+
protected _recycle(connection: Connection): Promise<boolean>;
|
|
131
|
+
/** Adopt a connection tying it to our events */
|
|
132
|
+
private _adopt;
|
|
133
|
+
/** Destroy a connection, it will be wiped from this pool */
|
|
134
|
+
private _evict;
|
|
135
|
+
/**
|
|
136
|
+
* Run the create connection loop.
|
|
137
|
+
*
|
|
138
|
+
* This loop simply creates connections, connects them, sets up the various
|
|
139
|
+
* event handler (on disconnect) and simply adds them to the available array.
|
|
140
|
+
*/
|
|
141
|
+
private _runCreateLoop;
|
|
142
|
+
/**
|
|
143
|
+
* Run the borrow connection loop.
|
|
144
|
+
*
|
|
145
|
+
* This loop looks at all the pending connection requests, and fullfills them
|
|
146
|
+
* with a connection from the available array. If no connections are available
|
|
147
|
+
* then it simply triggers the create loop.
|
|
148
|
+
*/
|
|
149
|
+
private _runBorrowLoop;
|
|
150
|
+
/** Acquire a {@link Connection} from this {@link ConnectionPool} */
|
|
151
|
+
acquire(): Promise<Connection>;
|
|
152
|
+
/** Release a {@link Connection} back to this {@link ConnectionPool} */
|
|
153
|
+
release(connection: Connection): void;
|
|
154
|
+
/** Start this {@link ConnectionPool} validating an initial connection */
|
|
155
|
+
start(): Promise<this>;
|
|
156
|
+
/** Stop this {@link ConnectionPool} and disconnect all connections. */
|
|
157
|
+
stop(): void;
|
|
158
|
+
}
|
|
159
|
+
export {};
|