@qualithm/arrow-flight-sql-js 0.0.1

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.
Files changed (49) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +433 -0
  3. package/dist/arrow.d.ts +65 -0
  4. package/dist/arrow.d.ts.map +1 -0
  5. package/dist/arrow.js +250 -0
  6. package/dist/arrow.js.map +1 -0
  7. package/dist/client.d.ts +416 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +1087 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/errors.d.ts +128 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +181 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/generated/index.d.ts +4 -0
  16. package/dist/generated/index.d.ts.map +1 -0
  17. package/dist/generated/index.js +33 -0
  18. package/dist/generated/index.js.map +1 -0
  19. package/dist/index.d.ts +40 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +43 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/metrics.d.ts +217 -0
  24. package/dist/metrics.d.ts.map +1 -0
  25. package/dist/metrics.js +304 -0
  26. package/dist/metrics.js.map +1 -0
  27. package/dist/pool.d.ts +161 -0
  28. package/dist/pool.d.ts.map +1 -0
  29. package/dist/pool.js +434 -0
  30. package/dist/pool.js.map +1 -0
  31. package/dist/proto.d.ts +168 -0
  32. package/dist/proto.d.ts.map +1 -0
  33. package/dist/proto.js +417 -0
  34. package/dist/proto.js.map +1 -0
  35. package/dist/query-builder.d.ts +1 -0
  36. package/dist/query-builder.d.ts.map +1 -0
  37. package/dist/query-builder.js +3 -0
  38. package/dist/query-builder.js.map +1 -0
  39. package/dist/retry.d.ts +92 -0
  40. package/dist/retry.d.ts.map +1 -0
  41. package/dist/retry.js +212 -0
  42. package/dist/retry.js.map +1 -0
  43. package/dist/types.d.ts +325 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +18 -0
  46. package/dist/types.js.map +1 -0
  47. package/package.json +82 -0
  48. package/proto/Flight.proto +645 -0
  49. package/proto/FlightSql.proto +1925 -0
package/dist/pool.d.ts ADDED
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Connection Pool for Arrow Flight SQL clients.
3
+ *
4
+ * Provides efficient connection reuse with:
5
+ * - Configurable pool size limits
6
+ * - Automatic connection health checking
7
+ * - Idle connection timeout
8
+ * - FIFO connection acquisition
9
+ * - Graceful shutdown support
10
+ */
11
+ import { FlightSqlClient } from "./client";
12
+ import type { RetryPolicy } from "./retry";
13
+ import type { FlightSqlClientOptions, PoolOptions, PoolStats } from "./types";
14
+ /**
15
+ * Connection pool for FlightSqlClient instances.
16
+ *
17
+ * Manages a pool of connections to a Flight SQL server, handling:
18
+ * - Connection reuse to reduce overhead
19
+ * - Automatic scaling between min and max connections
20
+ * - Health checking to ensure connection validity
21
+ * - Graceful shutdown with connection draining
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const pool = new FlightSqlPool({
26
+ * host: "localhost",
27
+ * port: 50051,
28
+ * tls: false,
29
+ * auth: { type: "bearer", token: "my-token" }
30
+ * }, {
31
+ * minConnections: 2,
32
+ * maxConnections: 10,
33
+ * idleTimeoutMs: 30000
34
+ * })
35
+ *
36
+ * await pool.initialize()
37
+ *
38
+ * // Acquire a connection
39
+ * const client = await pool.acquire()
40
+ * try {
41
+ * const result = await client.query("SELECT 1")
42
+ * // Use result...
43
+ * } finally {
44
+ * pool.release(client)
45
+ * }
46
+ *
47
+ * // Or use withConnection for automatic release
48
+ * await pool.withConnection(async (client) => {
49
+ * const result = await client.query("SELECT 1")
50
+ * // Use result...
51
+ * })
52
+ *
53
+ * await pool.close()
54
+ * ```
55
+ */
56
+ export declare class FlightSqlPool {
57
+ private readonly clientOptions;
58
+ private readonly poolOptions;
59
+ private readonly retryPolicy;
60
+ private connections;
61
+ private pendingRequests;
62
+ private nextConnectionId;
63
+ private initialized;
64
+ private closing;
65
+ private closed;
66
+ private healthCheckTimer;
67
+ private idleCheckTimer;
68
+ constructor(clientOptions: FlightSqlClientOptions, poolOptions?: PoolOptions, retryPolicy?: RetryPolicy);
69
+ /**
70
+ * Initialize the pool and create minimum connections.
71
+ *
72
+ * @throws {ConnectionError} If initial connections cannot be established
73
+ */
74
+ initialize(): Promise<void>;
75
+ /**
76
+ * Close the pool and all connections gracefully.
77
+ * Waits for active connections to be released.
78
+ *
79
+ * @param forceTimeoutMs - Force close after this timeout (default: 30000)
80
+ */
81
+ close(forceTimeoutMs?: number): Promise<void>;
82
+ /**
83
+ * Check if the pool is initialized and ready
84
+ */
85
+ get isInitialized(): boolean;
86
+ /**
87
+ * Check if the pool is closed
88
+ */
89
+ get isClosed(): boolean;
90
+ /**
91
+ * Acquire a connection from the pool.
92
+ *
93
+ * @throws {TimeoutError} If no connection becomes available within acquireTimeoutMs
94
+ * @throws {Error} If pool is closing or closed
95
+ */
96
+ acquire(): Promise<FlightSqlClient>;
97
+ /**
98
+ * Release a connection back to the pool.
99
+ *
100
+ * @param client - The client to release
101
+ */
102
+ release(client: FlightSqlClient): void;
103
+ /**
104
+ * Execute a function with a pooled connection, automatically releasing it.
105
+ *
106
+ * @param fn - Function to execute with the connection
107
+ * @returns The result of the function
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * const result = await pool.withConnection(async (client) => {
112
+ * return await client.query("SELECT * FROM users")
113
+ * })
114
+ * ```
115
+ */
116
+ withConnection<T>(fn: (client: FlightSqlClient) => Promise<T>): Promise<T>;
117
+ /**
118
+ * Execute a function with retry logic and automatic connection management.
119
+ *
120
+ * @param fn - Function to execute
121
+ * @returns The result of the function
122
+ */
123
+ withRetry<T>(fn: (client: FlightSqlClient) => Promise<T>): Promise<T>;
124
+ /**
125
+ * Get current pool statistics.
126
+ */
127
+ getStats(): PoolStats;
128
+ /**
129
+ * Create a new connection and add it to the pool
130
+ */
131
+ private createConnection;
132
+ /**
133
+ * Get an idle connection from the pool
134
+ */
135
+ private getIdleConnection;
136
+ /**
137
+ * Wait for a connection to become available
138
+ */
139
+ private waitForConnection;
140
+ /**
141
+ * Run health checks on idle connections
142
+ */
143
+ private runHealthChecks;
144
+ /**
145
+ * Clean up idle connections that have exceeded the timeout
146
+ */
147
+ private cleanupIdleConnections;
148
+ /**
149
+ * Ensure minimum number of connections are maintained
150
+ */
151
+ private ensureMinConnections;
152
+ /**
153
+ * Remove a connection from the pool
154
+ */
155
+ private removeConnection;
156
+ /**
157
+ * Close all connections in the pool
158
+ */
159
+ private closeAllConnections;
160
+ }
161
+ //# sourceMappingURL=pool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAE1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C,OAAO,KAAK,EAAE,sBAAsB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAwC7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwB;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAa;IAEzC,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,MAAM,CAAQ;IAEtB,OAAO,CAAC,gBAAgB,CAA8C;IACtE,OAAO,CAAC,cAAc,CAA8C;gBAGlE,aAAa,EAAE,sBAAsB,EACrC,WAAW,GAAE,WAAgB,EAC7B,WAAW,GAAE,WAAmC;IAmBlD;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAyCjC;;;;;OAKG;IACG,KAAK,CAAC,cAAc,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAwCnD;;OAEG;IACH,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAMD;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,eAAe,CAAC;IAoCzC;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAsBtC;;;;;;;;;;;;OAYG;IACG,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAShF;;;;;OAKG;IACG,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAW3E;;OAEG;IACH,QAAQ,IAAI,SAAS;IAarB;;OAEG;YACW,gBAAgB;IAkB9B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAKzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAuBzB;;OAEG;YACW,eAAe;IA4B7B;;OAEG;YACW,sBAAsB;IAqBpC;;OAEG;YACW,oBAAoB;IAWlC;;OAEG;YACW,gBAAgB;IAgB9B;;OAEG;YACW,mBAAmB;CAelC"}
package/dist/pool.js ADDED
@@ -0,0 +1,434 @@
1
+ /**
2
+ * Connection Pool for Arrow Flight SQL clients.
3
+ *
4
+ * Provides efficient connection reuse with:
5
+ * - Configurable pool size limits
6
+ * - Automatic connection health checking
7
+ * - Idle connection timeout
8
+ * - FIFO connection acquisition
9
+ * - Graceful shutdown support
10
+ */
11
+ import { FlightSqlClient } from "./client";
12
+ import { TimeoutError } from "./errors";
13
+ import { retryPolicies } from "./retry";
14
+ // Default pool configuration
15
+ const defaultPoolOptions = {
16
+ minConnections: 0,
17
+ maxConnections: 10,
18
+ idleTimeoutMs: 30_000,
19
+ acquireTimeoutMs: 10_000,
20
+ healthCheck: true,
21
+ healthCheckIntervalMs: 30_000
22
+ };
23
+ /**
24
+ * Connection pool for FlightSqlClient instances.
25
+ *
26
+ * Manages a pool of connections to a Flight SQL server, handling:
27
+ * - Connection reuse to reduce overhead
28
+ * - Automatic scaling between min and max connections
29
+ * - Health checking to ensure connection validity
30
+ * - Graceful shutdown with connection draining
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * const pool = new FlightSqlPool({
35
+ * host: "localhost",
36
+ * port: 50051,
37
+ * tls: false,
38
+ * auth: { type: "bearer", token: "my-token" }
39
+ * }, {
40
+ * minConnections: 2,
41
+ * maxConnections: 10,
42
+ * idleTimeoutMs: 30000
43
+ * })
44
+ *
45
+ * await pool.initialize()
46
+ *
47
+ * // Acquire a connection
48
+ * const client = await pool.acquire()
49
+ * try {
50
+ * const result = await client.query("SELECT 1")
51
+ * // Use result...
52
+ * } finally {
53
+ * pool.release(client)
54
+ * }
55
+ *
56
+ * // Or use withConnection for automatic release
57
+ * await pool.withConnection(async (client) => {
58
+ * const result = await client.query("SELECT 1")
59
+ * // Use result...
60
+ * })
61
+ *
62
+ * await pool.close()
63
+ * ```
64
+ */
65
+ export class FlightSqlPool {
66
+ clientOptions;
67
+ poolOptions;
68
+ retryPolicy;
69
+ connections = [];
70
+ pendingRequests = [];
71
+ nextConnectionId = 1;
72
+ initialized = false;
73
+ closing = false;
74
+ closed = false;
75
+ healthCheckTimer = null;
76
+ idleCheckTimer = null;
77
+ constructor(clientOptions, poolOptions = {}, retryPolicy = retryPolicies.default) {
78
+ this.clientOptions = clientOptions;
79
+ this.poolOptions = { ...defaultPoolOptions, ...poolOptions };
80
+ this.retryPolicy = retryPolicy;
81
+ // Validate options
82
+ if (this.poolOptions.minConnections > this.poolOptions.maxConnections) {
83
+ throw new Error("minConnections cannot be greater than maxConnections");
84
+ }
85
+ if (this.poolOptions.minConnections < 0) {
86
+ throw new Error("minConnections cannot be negative");
87
+ }
88
+ }
89
+ // ===========================================================================
90
+ // Lifecycle
91
+ // ===========================================================================
92
+ /**
93
+ * Initialize the pool and create minimum connections.
94
+ *
95
+ * @throws {ConnectionError} If initial connections cannot be established
96
+ */
97
+ async initialize() {
98
+ if (this.initialized) {
99
+ return;
100
+ }
101
+ if (this.closed) {
102
+ throw new Error("Pool has been closed");
103
+ }
104
+ // Create minimum connections in parallel
105
+ const connectionPromises = [];
106
+ for (let i = 0; i < this.poolOptions.minConnections; i++) {
107
+ connectionPromises.push(this.createConnection());
108
+ }
109
+ try {
110
+ await Promise.all(connectionPromises);
111
+ }
112
+ catch (error) {
113
+ // Clean up any connections that were created
114
+ await this.closeAllConnections();
115
+ throw error;
116
+ }
117
+ // Start health check timer if enabled
118
+ if (this.poolOptions.healthCheck && this.poolOptions.healthCheckIntervalMs > 0) {
119
+ this.healthCheckTimer = setInterval(() => void this.runHealthChecks(), this.poolOptions.healthCheckIntervalMs);
120
+ }
121
+ // Start idle connection cleanup timer
122
+ if (this.poolOptions.idleTimeoutMs > 0) {
123
+ this.idleCheckTimer = setInterval(() => void this.cleanupIdleConnections(), this.poolOptions.idleTimeoutMs / 2);
124
+ }
125
+ this.initialized = true;
126
+ }
127
+ /**
128
+ * Close the pool and all connections gracefully.
129
+ * Waits for active connections to be released.
130
+ *
131
+ * @param forceTimeoutMs - Force close after this timeout (default: 30000)
132
+ */
133
+ async close(forceTimeoutMs = 30_000) {
134
+ if (this.closed) {
135
+ return;
136
+ }
137
+ this.closing = true;
138
+ // Stop timers
139
+ if (this.healthCheckTimer) {
140
+ clearInterval(this.healthCheckTimer);
141
+ this.healthCheckTimer = null;
142
+ }
143
+ if (this.idleCheckTimer) {
144
+ clearInterval(this.idleCheckTimer);
145
+ this.idleCheckTimer = null;
146
+ }
147
+ // Reject all pending requests
148
+ for (const request of this.pendingRequests) {
149
+ clearTimeout(request.timeoutId);
150
+ request.reject(new Error("Pool is closing"));
151
+ }
152
+ this.pendingRequests = [];
153
+ // Wait for active connections to be released
154
+ const startTime = Date.now();
155
+ while (this.connections.some((c) => c.inUse)) {
156
+ if (Date.now() - startTime > forceTimeoutMs) {
157
+ break; // Force close after timeout
158
+ }
159
+ await new Promise((resolve) => setTimeout(resolve, 100));
160
+ }
161
+ // Close all connections
162
+ await this.closeAllConnections();
163
+ this.closed = true;
164
+ this.initialized = false;
165
+ }
166
+ /**
167
+ * Check if the pool is initialized and ready
168
+ */
169
+ get isInitialized() {
170
+ return this.initialized && !this.closing && !this.closed;
171
+ }
172
+ /**
173
+ * Check if the pool is closed
174
+ */
175
+ get isClosed() {
176
+ return this.closed;
177
+ }
178
+ // ===========================================================================
179
+ // Connection Acquisition
180
+ // ===========================================================================
181
+ /**
182
+ * Acquire a connection from the pool.
183
+ *
184
+ * @throws {TimeoutError} If no connection becomes available within acquireTimeoutMs
185
+ * @throws {Error} If pool is closing or closed
186
+ */
187
+ async acquire() {
188
+ if (this.closing || this.closed) {
189
+ throw new Error("Pool is closing or closed");
190
+ }
191
+ if (!this.initialized) {
192
+ await this.initialize();
193
+ }
194
+ // Try to get an idle connection
195
+ const idleConnection = this.getIdleConnection();
196
+ if (idleConnection) {
197
+ idleConnection.inUse = true;
198
+ idleConnection.lastUsedAt = Date.now();
199
+ return idleConnection.client;
200
+ }
201
+ // Try to create a new connection if under limit
202
+ if (this.connections.length < this.poolOptions.maxConnections) {
203
+ try {
204
+ await this.createConnection();
205
+ const newConnection = this.getIdleConnection();
206
+ if (newConnection) {
207
+ newConnection.inUse = true;
208
+ newConnection.lastUsedAt = Date.now();
209
+ return newConnection.client;
210
+ }
211
+ }
212
+ catch {
213
+ // Failed to create connection, fall through to waiting
214
+ }
215
+ }
216
+ // Wait for a connection to become available
217
+ return this.waitForConnection();
218
+ }
219
+ /**
220
+ * Release a connection back to the pool.
221
+ *
222
+ * @param client - The client to release
223
+ */
224
+ release(client) {
225
+ const connection = this.connections.find((c) => c.client === client);
226
+ if (!connection) {
227
+ // Connection not from this pool or already removed
228
+ return;
229
+ }
230
+ connection.inUse = false;
231
+ connection.lastUsedAt = Date.now();
232
+ // Check if there are pending requests waiting for a connection
233
+ if (this.pendingRequests.length > 0) {
234
+ const request = this.pendingRequests.shift();
235
+ if (request) {
236
+ clearTimeout(request.timeoutId);
237
+ connection.inUse = true;
238
+ connection.lastUsedAt = Date.now();
239
+ request.resolve(connection.client);
240
+ }
241
+ }
242
+ }
243
+ /**
244
+ * Execute a function with a pooled connection, automatically releasing it.
245
+ *
246
+ * @param fn - Function to execute with the connection
247
+ * @returns The result of the function
248
+ *
249
+ * @example
250
+ * ```typescript
251
+ * const result = await pool.withConnection(async (client) => {
252
+ * return await client.query("SELECT * FROM users")
253
+ * })
254
+ * ```
255
+ */
256
+ async withConnection(fn) {
257
+ const client = await this.acquire();
258
+ try {
259
+ return await fn(client);
260
+ }
261
+ finally {
262
+ this.release(client);
263
+ }
264
+ }
265
+ /**
266
+ * Execute a function with retry logic and automatic connection management.
267
+ *
268
+ * @param fn - Function to execute
269
+ * @returns The result of the function
270
+ */
271
+ async withRetry(fn) {
272
+ const result = await this.retryPolicy.execute(async () => {
273
+ return this.withConnection(fn);
274
+ });
275
+ return result.value;
276
+ }
277
+ // ===========================================================================
278
+ // Pool Statistics
279
+ // ===========================================================================
280
+ /**
281
+ * Get current pool statistics.
282
+ */
283
+ getStats() {
284
+ return {
285
+ totalConnections: this.connections.length,
286
+ activeConnections: this.connections.filter((c) => c.inUse).length,
287
+ idleConnections: this.connections.filter((c) => !c.inUse).length,
288
+ pendingRequests: this.pendingRequests.length
289
+ };
290
+ }
291
+ // ===========================================================================
292
+ // Private Methods
293
+ // ===========================================================================
294
+ /**
295
+ * Create a new connection and add it to the pool
296
+ */
297
+ async createConnection() {
298
+ const client = new FlightSqlClient(this.clientOptions);
299
+ await this.retryPolicy.execute(async () => {
300
+ await client.connect();
301
+ });
302
+ const now = Date.now();
303
+ this.connections.push({
304
+ client,
305
+ createdAt: now,
306
+ lastUsedAt: now,
307
+ lastHealthCheckAt: now,
308
+ inUse: false,
309
+ id: this.nextConnectionId++
310
+ });
311
+ }
312
+ /**
313
+ * Get an idle connection from the pool
314
+ */
315
+ getIdleConnection() {
316
+ // FIFO: Return the least recently used idle connection
317
+ return this.connections.filter((c) => !c.inUse).sort((a, b) => a.lastUsedAt - b.lastUsedAt)[0];
318
+ }
319
+ /**
320
+ * Wait for a connection to become available
321
+ */
322
+ waitForConnection() {
323
+ return new Promise((resolve, reject) => {
324
+ const timeoutId = setTimeout(() => {
325
+ const index = this.pendingRequests.findIndex((r) => r.timeoutId === timeoutId);
326
+ if (index >= 0) {
327
+ this.pendingRequests.splice(index, 1);
328
+ }
329
+ reject(new TimeoutError(`Timed out waiting for connection after ${String(this.poolOptions.acquireTimeoutMs)}ms`));
330
+ }, this.poolOptions.acquireTimeoutMs);
331
+ this.pendingRequests.push({
332
+ resolve,
333
+ reject,
334
+ timeoutId,
335
+ createdAt: Date.now()
336
+ });
337
+ });
338
+ }
339
+ /**
340
+ * Run health checks on idle connections
341
+ */
342
+ async runHealthChecks() {
343
+ if (this.closing || this.closed) {
344
+ return;
345
+ }
346
+ const now = Date.now();
347
+ const idleConnections = this.connections.filter((c) => !c.inUse && now - c.lastHealthCheckAt > this.poolOptions.healthCheckIntervalMs);
348
+ for (const connection of idleConnections) {
349
+ try {
350
+ // Simple health check: try to get flight info for empty command
351
+ // This validates the connection is still alive
352
+ connection.inUse = true;
353
+ await connection.client.listActions();
354
+ connection.lastHealthCheckAt = Date.now();
355
+ connection.inUse = false;
356
+ }
357
+ catch {
358
+ // Connection is unhealthy, remove it
359
+ await this.removeConnection(connection);
360
+ }
361
+ }
362
+ // Ensure minimum connections
363
+ await this.ensureMinConnections();
364
+ }
365
+ /**
366
+ * Clean up idle connections that have exceeded the timeout
367
+ */
368
+ async cleanupIdleConnections() {
369
+ if (this.closing || this.closed) {
370
+ return;
371
+ }
372
+ const now = Date.now();
373
+ const expiredConnections = this.connections.filter((c) => !c.inUse &&
374
+ now - c.lastUsedAt > this.poolOptions.idleTimeoutMs &&
375
+ this.connections.length > this.poolOptions.minConnections);
376
+ for (const connection of expiredConnections) {
377
+ // Only remove if we're still above minimum
378
+ if (this.connections.length > this.poolOptions.minConnections) {
379
+ await this.removeConnection(connection);
380
+ }
381
+ }
382
+ }
383
+ /**
384
+ * Ensure minimum number of connections are maintained
385
+ */
386
+ async ensureMinConnections() {
387
+ while (this.connections.length < this.poolOptions.minConnections) {
388
+ try {
389
+ await this.createConnection();
390
+ }
391
+ catch {
392
+ // Failed to create connection, try again on next check
393
+ break;
394
+ }
395
+ }
396
+ }
397
+ /**
398
+ * Remove a connection from the pool
399
+ */
400
+ async removeConnection(connection) {
401
+ const index = this.connections.indexOf(connection);
402
+ if (index >= 0) {
403
+ this.connections.splice(index, 1);
404
+ }
405
+ try {
406
+ // close() returns void but may be async internally
407
+ connection.client.close();
408
+ // Small delay to allow cleanup
409
+ await new Promise((resolve) => setTimeout(resolve, 0));
410
+ }
411
+ catch {
412
+ // Ignore close errors
413
+ }
414
+ }
415
+ /**
416
+ * Close all connections in the pool
417
+ */
418
+ async closeAllConnections() {
419
+ const closePromises = this.connections.map(async (connection) => {
420
+ try {
421
+ // close() returns void but may be async internally
422
+ connection.client.close();
423
+ // Small delay to allow cleanup
424
+ await new Promise((resolve) => setTimeout(resolve, 0));
425
+ }
426
+ catch {
427
+ // Ignore close errors
428
+ }
429
+ });
430
+ await Promise.all(closePromises);
431
+ this.connections = [];
432
+ }
433
+ }
434
+ //# sourceMappingURL=pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"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"}