@agentuity/postgres 1.0.1 → 1.0.3
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/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/pool.d.ts +194 -0
- package/dist/pool.d.ts.map +1 -0
- package/dist/pool.js +574 -0
- package/dist/pool.js.map +1 -0
- package/dist/registry.d.ts +39 -22
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +33 -33
- package/dist/registry.js.map +1 -1
- package/dist/types.d.ts +155 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +8 -5
- package/src/index.ts +13 -1
- package/src/pool.ts +661 -0
- package/src/registry.ts +56 -37
- package/src/types.ts +186 -0
package/src/registry.ts
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Global registry for PostgreSQL clients.
|
|
2
|
+
* Global registry for PostgreSQL clients and pools.
|
|
3
3
|
*
|
|
4
|
-
* This module provides a way to track all active PostgreSQL clients
|
|
4
|
+
* This module provides a way to track all active PostgreSQL clients and pools
|
|
5
5
|
* so they can be gracefully shut down together (e.g., on process exit).
|
|
6
6
|
*
|
|
7
|
-
* The runtime can use `shutdownAll()` to close all registered clients
|
|
7
|
+
* The runtime can use `shutdownAll()` to close all registered clients/pools
|
|
8
8
|
* during graceful shutdown.
|
|
9
9
|
*
|
|
10
10
|
* When @agentuity/runtime is available, this module automatically registers
|
|
11
|
-
* a shutdown hook so all postgres clients are closed during graceful shutdown.
|
|
11
|
+
* a shutdown hook so all postgres clients/pools are closed during graceful shutdown.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Common interface for registrable PostgreSQL connections.
|
|
16
|
+
* Both PostgresClient and PostgresPool implement this interface.
|
|
17
|
+
*/
|
|
18
|
+
export interface Registrable {
|
|
19
|
+
/**
|
|
20
|
+
* Whether the connection is shutting down.
|
|
21
|
+
*/
|
|
22
|
+
readonly shuttingDown: boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Signal that the connection is shutting down.
|
|
26
|
+
*/
|
|
27
|
+
shutdown(): void;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Close the connection.
|
|
31
|
+
*/
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
}
|
|
15
34
|
|
|
16
35
|
/**
|
|
17
36
|
* Symbol used to store the registry in globalThis to avoid conflicts.
|
|
@@ -24,10 +43,10 @@ const REGISTRY_KEY = Symbol.for('@agentuity/postgres:registry');
|
|
|
24
43
|
const RUNTIME_HOOK_REGISTERED = Symbol.for('@agentuity/postgres:runtime-hook-registered');
|
|
25
44
|
|
|
26
45
|
/**
|
|
27
|
-
* Gets the global
|
|
46
|
+
* Gets the global registry, creating it if it doesn't exist.
|
|
28
47
|
*/
|
|
29
|
-
function getRegistry(): Set<
|
|
30
|
-
const global = globalThis as Record<symbol, Set<
|
|
48
|
+
function getRegistry(): Set<Registrable> {
|
|
49
|
+
const global = globalThis as Record<symbol, Set<Registrable>>;
|
|
31
50
|
if (!global[REGISTRY_KEY]) {
|
|
32
51
|
global[REGISTRY_KEY] = new Set();
|
|
33
52
|
}
|
|
@@ -35,29 +54,29 @@ function getRegistry(): Set<PostgresClient> {
|
|
|
35
54
|
}
|
|
36
55
|
|
|
37
56
|
/**
|
|
38
|
-
* Registers a client in the global registry.
|
|
39
|
-
* Called automatically when a client is created.
|
|
57
|
+
* Registers a client or pool in the global registry.
|
|
58
|
+
* Called automatically when a client or pool is created.
|
|
40
59
|
*
|
|
41
|
-
* @param
|
|
60
|
+
* @param connection - The client or pool to register
|
|
42
61
|
* @internal
|
|
43
62
|
*/
|
|
44
|
-
export function registerClient(
|
|
45
|
-
getRegistry().add(
|
|
63
|
+
export function registerClient(connection: Registrable): void {
|
|
64
|
+
getRegistry().add(connection);
|
|
46
65
|
}
|
|
47
66
|
|
|
48
67
|
/**
|
|
49
|
-
* Unregisters a client from the global registry.
|
|
50
|
-
* Called automatically when a client is closed.
|
|
68
|
+
* Unregisters a client or pool from the global registry.
|
|
69
|
+
* Called automatically when a client or pool is closed.
|
|
51
70
|
*
|
|
52
|
-
* @param
|
|
71
|
+
* @param connection - The client or pool to unregister
|
|
53
72
|
* @internal
|
|
54
73
|
*/
|
|
55
|
-
export function unregisterClient(
|
|
56
|
-
getRegistry().delete(
|
|
74
|
+
export function unregisterClient(connection: Registrable): void {
|
|
75
|
+
getRegistry().delete(connection);
|
|
57
76
|
}
|
|
58
77
|
|
|
59
78
|
/**
|
|
60
|
-
* Returns the number of registered clients.
|
|
79
|
+
* Returns the number of registered clients and pools.
|
|
61
80
|
* Useful for debugging and testing.
|
|
62
81
|
*/
|
|
63
82
|
export function getClientCount(): number {
|
|
@@ -65,27 +84,27 @@ export function getClientCount(): number {
|
|
|
65
84
|
}
|
|
66
85
|
|
|
67
86
|
/**
|
|
68
|
-
* Returns all registered clients.
|
|
87
|
+
* Returns all registered clients and pools.
|
|
69
88
|
* Useful for debugging and monitoring.
|
|
70
89
|
*/
|
|
71
|
-
export function getClients(): ReadonlySet<
|
|
90
|
+
export function getClients(): ReadonlySet<Registrable> {
|
|
72
91
|
return getRegistry();
|
|
73
92
|
}
|
|
74
93
|
|
|
75
94
|
/**
|
|
76
|
-
* Shuts down all registered PostgreSQL clients gracefully.
|
|
95
|
+
* Shuts down all registered PostgreSQL clients and pools gracefully.
|
|
77
96
|
*
|
|
78
97
|
* This function:
|
|
79
|
-
* 1. Signals shutdown to all clients (prevents reconnection)
|
|
80
|
-
* 2. Closes all clients in parallel
|
|
98
|
+
* 1. Signals shutdown to all clients/pools (prevents reconnection)
|
|
99
|
+
* 2. Closes all clients/pools in parallel
|
|
81
100
|
* 3. Clears the registry
|
|
82
101
|
*
|
|
83
102
|
* This is intended to be called by the runtime during graceful shutdown.
|
|
84
103
|
*
|
|
85
104
|
* @param timeoutMs - Optional timeout in milliseconds. If provided, the function
|
|
86
|
-
* will resolve after the timeout even if some
|
|
105
|
+
* will resolve after the timeout even if some connections haven't
|
|
87
106
|
* finished closing. Default: no timeout.
|
|
88
|
-
* @returns A promise that resolves when all
|
|
107
|
+
* @returns A promise that resolves when all connections are closed (or timeout)
|
|
89
108
|
*
|
|
90
109
|
* @example
|
|
91
110
|
* ```typescript
|
|
@@ -99,21 +118,21 @@ export function getClients(): ReadonlySet<PostgresClient> {
|
|
|
99
118
|
*/
|
|
100
119
|
export async function shutdownAll(timeoutMs?: number): Promise<void> {
|
|
101
120
|
const registry = getRegistry();
|
|
102
|
-
const
|
|
121
|
+
const connections = Array.from(registry);
|
|
103
122
|
|
|
104
|
-
if (
|
|
123
|
+
if (connections.length === 0) {
|
|
105
124
|
return;
|
|
106
125
|
}
|
|
107
126
|
|
|
108
|
-
// Signal shutdown to all
|
|
109
|
-
for (const
|
|
110
|
-
|
|
127
|
+
// Signal shutdown to all connections first (prevents reconnection attempts)
|
|
128
|
+
for (const connection of connections) {
|
|
129
|
+
connection.shutdown();
|
|
111
130
|
}
|
|
112
131
|
|
|
113
|
-
// Close all
|
|
114
|
-
const closePromises =
|
|
132
|
+
// Close all connections in parallel
|
|
133
|
+
const closePromises = connections.map(async (connection) => {
|
|
115
134
|
try {
|
|
116
|
-
await
|
|
135
|
+
await connection.close();
|
|
117
136
|
} catch {
|
|
118
137
|
// Ignore close errors during shutdown
|
|
119
138
|
}
|
|
@@ -141,13 +160,13 @@ export async function shutdownAll(timeoutMs?: number): Promise<void> {
|
|
|
141
160
|
}
|
|
142
161
|
|
|
143
162
|
/**
|
|
144
|
-
* Checks if there are any active (non-shutdown) clients.
|
|
163
|
+
* Checks if there are any active (non-shutdown) clients or pools.
|
|
145
164
|
* Useful for health checks.
|
|
146
165
|
*/
|
|
147
166
|
export function hasActiveClients(): boolean {
|
|
148
167
|
const registry = getRegistry();
|
|
149
|
-
for (const
|
|
150
|
-
if (!
|
|
168
|
+
for (const connection of registry) {
|
|
169
|
+
if (!connection.shuttingDown) {
|
|
151
170
|
return true;
|
|
152
171
|
}
|
|
153
172
|
}
|
package/src/types.ts
CHANGED
|
@@ -248,3 +248,189 @@ export interface ReserveOptions {
|
|
|
248
248
|
*/
|
|
249
249
|
timeout?: number;
|
|
250
250
|
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* SSL configuration for pg.Pool connections.
|
|
254
|
+
*/
|
|
255
|
+
export interface PoolSSLConfig {
|
|
256
|
+
/**
|
|
257
|
+
* Whether to reject unauthorized certificates.
|
|
258
|
+
* Set to `false` to allow self-signed certificates.
|
|
259
|
+
*/
|
|
260
|
+
rejectUnauthorized?: boolean;
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* CA certificate(s) for verifying the server certificate.
|
|
264
|
+
*/
|
|
265
|
+
ca?: string | Buffer | (string | Buffer)[];
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Client certificate for mutual TLS authentication.
|
|
269
|
+
*/
|
|
270
|
+
cert?: string | Buffer;
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Client private key for mutual TLS authentication.
|
|
274
|
+
*/
|
|
275
|
+
key?: string | Buffer;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Configuration options for PostgresPool.
|
|
280
|
+
* Extends standard pg.Pool options with reconnection support.
|
|
281
|
+
*/
|
|
282
|
+
export interface PoolConfig {
|
|
283
|
+
/**
|
|
284
|
+
* PostgreSQL connection URL.
|
|
285
|
+
* If not provided, uses `process.env.DATABASE_URL`.
|
|
286
|
+
*/
|
|
287
|
+
connectionString?: string;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Database hostname.
|
|
291
|
+
*/
|
|
292
|
+
host?: string;
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Database port.
|
|
296
|
+
* @default 5432
|
|
297
|
+
*/
|
|
298
|
+
port?: number;
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Database username.
|
|
302
|
+
*/
|
|
303
|
+
user?: string;
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Database password.
|
|
307
|
+
*/
|
|
308
|
+
password?: string;
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Database name.
|
|
312
|
+
*/
|
|
313
|
+
database?: string;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Maximum number of connections in the pool.
|
|
317
|
+
* @default 10
|
|
318
|
+
*/
|
|
319
|
+
max?: number;
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Number of milliseconds a client must sit idle before being disconnected.
|
|
323
|
+
* Set to 0 to disable idle timeout.
|
|
324
|
+
* @default 10000
|
|
325
|
+
*/
|
|
326
|
+
idleTimeoutMillis?: number;
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Number of milliseconds to wait when connecting a new client before timing out.
|
|
330
|
+
* Set to 0 to disable connection timeout.
|
|
331
|
+
* @default 0
|
|
332
|
+
*/
|
|
333
|
+
connectionTimeoutMillis?: number;
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* SSL configuration.
|
|
337
|
+
* Set to `true` to enable SSL with default settings.
|
|
338
|
+
* Set to an object to configure SSL options.
|
|
339
|
+
* Set to `false` or omit to disable SSL.
|
|
340
|
+
*/
|
|
341
|
+
ssl?: boolean | PoolSSLConfig;
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Reconnection configuration.
|
|
345
|
+
*/
|
|
346
|
+
reconnect?: ReconnectConfig;
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Whether to establish a connection immediately on pool creation.
|
|
350
|
+
* If true, the pool will verify connectivity by acquiring and releasing a client.
|
|
351
|
+
* If false (default), the first connection is made lazily on first query.
|
|
352
|
+
*
|
|
353
|
+
* @default false
|
|
354
|
+
*/
|
|
355
|
+
preconnect?: boolean;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Callback invoked when the pool encounters an error.
|
|
359
|
+
*/
|
|
360
|
+
onclose?: (error?: Error) => void;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Callback invoked when reconnection starts.
|
|
364
|
+
*/
|
|
365
|
+
onreconnect?: (attempt: number) => void;
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Callback invoked when reconnection succeeds.
|
|
369
|
+
*/
|
|
370
|
+
onreconnected?: () => void;
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Callback invoked when reconnection fails permanently.
|
|
374
|
+
*/
|
|
375
|
+
onreconnectfailed?: (error: Error) => void;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Statistics about the pool state and reconnection history.
|
|
380
|
+
*/
|
|
381
|
+
export interface PoolStats {
|
|
382
|
+
/**
|
|
383
|
+
* Whether the pool is currently connected.
|
|
384
|
+
*/
|
|
385
|
+
connected: boolean;
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Whether a reconnection attempt is in progress.
|
|
389
|
+
*/
|
|
390
|
+
reconnecting: boolean;
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Total number of clients in the pool.
|
|
394
|
+
*/
|
|
395
|
+
totalCount: number;
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Number of idle clients in the pool.
|
|
399
|
+
*/
|
|
400
|
+
idleCount: number;
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Number of clients currently waiting to be acquired.
|
|
404
|
+
*/
|
|
405
|
+
waitingCount: number;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Total number of successful connections (including reconnections).
|
|
409
|
+
*/
|
|
410
|
+
totalConnections: number;
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Total number of reconnection attempts.
|
|
414
|
+
*/
|
|
415
|
+
reconnectAttempts: number;
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Total number of failed reconnection attempts.
|
|
419
|
+
*/
|
|
420
|
+
failedReconnects: number;
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Timestamp of the last successful connection.
|
|
424
|
+
*/
|
|
425
|
+
lastConnectedAt: Date | null;
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Timestamp of the last disconnection.
|
|
429
|
+
*/
|
|
430
|
+
lastDisconnectedAt: Date | null;
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Timestamp of the last reconnection attempt.
|
|
434
|
+
*/
|
|
435
|
+
lastReconnectAttemptAt: Date | null;
|
|
436
|
+
}
|