@naman_deep_singh/communication-core 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.
Files changed (134) hide show
  1. package/README.md +345 -0
  2. package/dist/cjs/abstract/BaseCircuitBreaker.js +253 -0
  3. package/dist/cjs/abstract/BaseClient.js +298 -0
  4. package/dist/cjs/abstract/BaseCompressionManager.js +377 -0
  5. package/dist/cjs/abstract/BaseConnectionPool.js +543 -0
  6. package/dist/cjs/abstract/BaseInterceptor.js +235 -0
  7. package/dist/cjs/abstract/BaseLoadBalancer.js +269 -0
  8. package/dist/cjs/abstract/BaseProtocol.js +269 -0
  9. package/dist/cjs/abstract/BaseRetryStrategy.js +255 -0
  10. package/dist/cjs/abstract/BaseSerializer.js +341 -0
  11. package/dist/cjs/abstract/BaseServiceDiscoverer.js +254 -0
  12. package/dist/cjs/abstract/BaseTimeoutManager.js +295 -0
  13. package/dist/cjs/abstract/index.js +25 -0
  14. package/dist/cjs/errors/CircuitBreakerError.js +16 -0
  15. package/dist/cjs/errors/CommunicationError.js +15 -0
  16. package/dist/cjs/errors/ConnectionError.js +15 -0
  17. package/dist/cjs/errors/DiscoveryError.js +15 -0
  18. package/dist/cjs/errors/LoadBalancerError.js +15 -0
  19. package/dist/cjs/errors/ProtocolError.js +15 -0
  20. package/dist/cjs/errors/RetryError.js +16 -0
  21. package/dist/cjs/errors/SerializationError.js +15 -0
  22. package/dist/cjs/errors/ServiceUnavailableError.js +15 -0
  23. package/dist/cjs/errors/TimeoutError.js +16 -0
  24. package/dist/cjs/errors/communicationErrorCodes.js +35 -0
  25. package/dist/cjs/errors/index.js +31 -0
  26. package/dist/cjs/index.js +38 -0
  27. package/dist/cjs/interfaces/CircuitBreaker.interface.js +6 -0
  28. package/dist/cjs/interfaces/Client.interface.js +6 -0
  29. package/dist/cjs/interfaces/Compression.interface.js +6 -0
  30. package/dist/cjs/interfaces/ConnectionPool.interface.js +6 -0
  31. package/dist/cjs/interfaces/Interceptor.interface.js +6 -0
  32. package/dist/cjs/interfaces/LoadBalancer.interface.js +2 -0
  33. package/dist/cjs/interfaces/Protocol.interface.js +6 -0
  34. package/dist/cjs/interfaces/RetryStrategy.interface.js +6 -0
  35. package/dist/cjs/interfaces/Serializer.interface.js +2 -0
  36. package/dist/cjs/interfaces/ServiceDiscovery.interface.js +6 -0
  37. package/dist/cjs/interfaces/Timeout.interface.js +6 -0
  38. package/dist/cjs/interfaces/index.js +6 -0
  39. package/dist/cjs/types/config.js +6 -0
  40. package/dist/cjs/types/events.js +6 -0
  41. package/dist/cjs/types/index.js +6 -0
  42. package/dist/cjs/types/request.js +6 -0
  43. package/dist/cjs/types/response.js +6 -0
  44. package/dist/cjs/types/service.js +6 -0
  45. package/dist/cjs/utils.js +200 -0
  46. package/dist/esm/abstract/BaseCircuitBreaker.js +249 -0
  47. package/dist/esm/abstract/BaseClient.js +294 -0
  48. package/dist/esm/abstract/BaseCompressionManager.js +373 -0
  49. package/dist/esm/abstract/BaseConnectionPool.js +539 -0
  50. package/dist/esm/abstract/BaseInterceptor.js +231 -0
  51. package/dist/esm/abstract/BaseLoadBalancer.js +265 -0
  52. package/dist/esm/abstract/BaseProtocol.js +265 -0
  53. package/dist/esm/abstract/BaseRetryStrategy.js +251 -0
  54. package/dist/esm/abstract/BaseSerializer.js +337 -0
  55. package/dist/esm/abstract/BaseServiceDiscoverer.js +250 -0
  56. package/dist/esm/abstract/BaseTimeoutManager.js +291 -0
  57. package/dist/esm/abstract/index.js +11 -0
  58. package/dist/esm/errors/CircuitBreakerError.js +12 -0
  59. package/dist/esm/errors/CommunicationError.js +11 -0
  60. package/dist/esm/errors/ConnectionError.js +11 -0
  61. package/dist/esm/errors/DiscoveryError.js +11 -0
  62. package/dist/esm/errors/LoadBalancerError.js +11 -0
  63. package/dist/esm/errors/ProtocolError.js +11 -0
  64. package/dist/esm/errors/RetryError.js +12 -0
  65. package/dist/esm/errors/SerializationError.js +11 -0
  66. package/dist/esm/errors/ServiceUnavailableError.js +11 -0
  67. package/dist/esm/errors/TimeoutError.js +12 -0
  68. package/dist/esm/errors/communicationErrorCodes.js +32 -0
  69. package/dist/esm/errors/index.js +17 -0
  70. package/dist/esm/index.js +18 -0
  71. package/dist/esm/interfaces/CircuitBreaker.interface.js +5 -0
  72. package/dist/esm/interfaces/Client.interface.js +5 -0
  73. package/dist/esm/interfaces/Compression.interface.js +5 -0
  74. package/dist/esm/interfaces/ConnectionPool.interface.js +5 -0
  75. package/dist/esm/interfaces/Interceptor.interface.js +5 -0
  76. package/dist/esm/interfaces/LoadBalancer.interface.js +1 -0
  77. package/dist/esm/interfaces/Protocol.interface.js +5 -0
  78. package/dist/esm/interfaces/RetryStrategy.interface.js +5 -0
  79. package/dist/esm/interfaces/Serializer.interface.js +1 -0
  80. package/dist/esm/interfaces/ServiceDiscovery.interface.js +5 -0
  81. package/dist/esm/interfaces/Timeout.interface.js +5 -0
  82. package/dist/esm/interfaces/index.js +5 -0
  83. package/dist/esm/types/config.js +5 -0
  84. package/dist/esm/types/events.js +5 -0
  85. package/dist/esm/types/index.js +5 -0
  86. package/dist/esm/types/request.js +5 -0
  87. package/dist/esm/types/response.js +5 -0
  88. package/dist/esm/types/service.js +5 -0
  89. package/dist/esm/utils.js +193 -0
  90. package/dist/types/abstract/BaseCircuitBreaker.d.ts +167 -0
  91. package/dist/types/abstract/BaseClient.d.ts +197 -0
  92. package/dist/types/abstract/BaseCompressionManager.d.ts +180 -0
  93. package/dist/types/abstract/BaseConnectionPool.d.ts +210 -0
  94. package/dist/types/abstract/BaseInterceptor.d.ts +150 -0
  95. package/dist/types/abstract/BaseLoadBalancer.d.ts +167 -0
  96. package/dist/types/abstract/BaseProtocol.d.ts +163 -0
  97. package/dist/types/abstract/BaseRetryStrategy.d.ts +130 -0
  98. package/dist/types/abstract/BaseSerializer.d.ts +181 -0
  99. package/dist/types/abstract/BaseServiceDiscoverer.d.ts +161 -0
  100. package/dist/types/abstract/BaseTimeoutManager.d.ts +145 -0
  101. package/dist/types/abstract/index.d.ts +11 -0
  102. package/dist/types/errors/CircuitBreakerError.d.ts +8 -0
  103. package/dist/types/errors/CommunicationError.d.ts +10 -0
  104. package/dist/types/errors/ConnectionError.d.ts +9 -0
  105. package/dist/types/errors/DiscoveryError.d.ts +9 -0
  106. package/dist/types/errors/LoadBalancerError.d.ts +9 -0
  107. package/dist/types/errors/ProtocolError.d.ts +9 -0
  108. package/dist/types/errors/RetryError.d.ts +11 -0
  109. package/dist/types/errors/SerializationError.d.ts +9 -0
  110. package/dist/types/errors/ServiceUnavailableError.d.ts +12 -0
  111. package/dist/types/errors/TimeoutError.d.ts +11 -0
  112. package/dist/types/errors/communicationErrorCodes.d.ts +27 -0
  113. package/dist/types/errors/index.d.ts +11 -0
  114. package/dist/types/index.d.ts +13 -0
  115. package/dist/types/interfaces/CircuitBreaker.interface.d.ts +150 -0
  116. package/dist/types/interfaces/Client.interface.d.ts +153 -0
  117. package/dist/types/interfaces/Compression.interface.d.ts +190 -0
  118. package/dist/types/interfaces/ConnectionPool.interface.d.ts +191 -0
  119. package/dist/types/interfaces/Interceptor.interface.d.ts +220 -0
  120. package/dist/types/interfaces/LoadBalancer.interface.d.ts +153 -0
  121. package/dist/types/interfaces/Protocol.interface.d.ts +117 -0
  122. package/dist/types/interfaces/RetryStrategy.interface.d.ts +160 -0
  123. package/dist/types/interfaces/Serializer.interface.d.ts +176 -0
  124. package/dist/types/interfaces/ServiceDiscovery.interface.d.ts +189 -0
  125. package/dist/types/interfaces/Timeout.interface.d.ts +135 -0
  126. package/dist/types/interfaces/index.d.ts +15 -0
  127. package/dist/types/types/config.d.ts +540 -0
  128. package/dist/types/types/events.d.ts +204 -0
  129. package/dist/types/types/index.d.ts +9 -0
  130. package/dist/types/types/request.d.ts +143 -0
  131. package/dist/types/types/response.d.ts +155 -0
  132. package/dist/types/types/service.d.ts +279 -0
  133. package/dist/types/utils.d.ts +179 -0
  134. package/package.json +88 -0
@@ -0,0 +1,543 @@
1
+ "use strict";
2
+ /**
3
+ * Abstract base connection pool implementation
4
+ * @packageDocumentation
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.BaseConnectionPool = void 0;
8
+ const CommunicationError_js_1 = require("../errors/CommunicationError.js");
9
+ const communicationErrorCodes_js_1 = require("../errors/communicationErrorCodes.js");
10
+ /**
11
+ * Abstract base connection pool implementation
12
+ * Provides common functionality for connection pooling
13
+ */
14
+ class BaseConnectionPool {
15
+ /**
16
+ * Create a new base connection pool instance
17
+ * @param name Pool name
18
+ * @param config Pool configuration
19
+ * @param createConnection Connection factory function
20
+ * @param validateConnection Connection validation function
21
+ */
22
+ constructor(name, config, createConnection, validateConnection) {
23
+ /** Is pool healthy? */
24
+ this.isHealthy = true;
25
+ /** Total connections in pool */
26
+ this.totalConnections = 0;
27
+ /** Active connections */
28
+ this.activeConnections = 0;
29
+ /** Idle connections */
30
+ this.idleConnections = 0;
31
+ /** Waiting clients */
32
+ this.waitingClients = 0;
33
+ /** Connection pool */
34
+ this.pool = new Set();
35
+ /** Active connections set */
36
+ this.activeConnectionsSet = new Set();
37
+ /** Idle connections queue */
38
+ this.idleConnectionsQueue = [];
39
+ /** Waiting clients queue */
40
+ this.waitingQueue = [];
41
+ /** Pool statistics */
42
+ this.stats = {
43
+ totalAcquisitions: 0,
44
+ totalReleases: 0,
45
+ totalDestructions: 0,
46
+ totalErrors: 0,
47
+ totalAcquisitionTime: 0,
48
+ maxAcquisitionTime: 0,
49
+ connectionStats: new Map(),
50
+ };
51
+ this.name = name;
52
+ this.config = { ...config };
53
+ this.createConnectionFn = createConnection;
54
+ this.validateConnectionFn = validateConnection || (async (conn) => conn.isHealthy());
55
+ this.initialize();
56
+ }
57
+ /**
58
+ * Initialize connection pool
59
+ */
60
+ async initialize() {
61
+ // Set up cleanup interval
62
+ if (this.config.validationInterval) {
63
+ this.cleanupInterval = setInterval(() => this.cleanupIdleConnections(), this.config.validationInterval);
64
+ }
65
+ // Set up health check interval
66
+ if (this.config.validationInterval) {
67
+ this.healthCheckInterval = setInterval(() => this.checkPoolHealth(), this.config.validationInterval);
68
+ }
69
+ // Warm up pool if configured
70
+ if (this.config.warmup && this.config.minConnections) {
71
+ await this.warmupPool();
72
+ }
73
+ }
74
+ /**
75
+ * Warm up the pool with minimum connections
76
+ */
77
+ async warmupPool() {
78
+ const minConnections = this.config.minConnections || 0;
79
+ const connectionsToCreate = Math.max(0, minConnections - this.totalConnections);
80
+ for (let i = 0; i < connectionsToCreate; i++) {
81
+ try {
82
+ const connection = await this.createConnection();
83
+ this.idleConnectionsQueue.push(connection);
84
+ this.pool.add(connection);
85
+ this.totalConnections++;
86
+ this.idleConnections++;
87
+ }
88
+ catch (error) {
89
+ // Log error but continue
90
+ this.stats.totalErrors++;
91
+ }
92
+ }
93
+ }
94
+ /**
95
+ * Acquire a connection from the pool
96
+ * @param timeout Acquisition timeout in milliseconds
97
+ * @returns Promise resolving to connection acquisition
98
+ * @throws {CommunicationError} If timeout or pool exhausted
99
+ */
100
+ async acquire(timeout) {
101
+ const startTime = Date.now();
102
+ const acquireTimeout = timeout || this.config.acquireTimeout || 10000;
103
+ // Check if we can create a new connection
104
+ if (this.activeConnections < (this.config.maxConnections || 10)) {
105
+ const connection = await this.getOrCreateConnection();
106
+ if (connection) {
107
+ const waitTime = Date.now() - startTime;
108
+ this.recordAcquisition(startTime, connection);
109
+ return this.createAcquisitionResult(connection, waitTime);
110
+ }
111
+ }
112
+ // If we can't create a new connection, wait for one to become available
113
+ return new Promise((resolve, reject) => {
114
+ const timer = setTimeout(() => {
115
+ this.removeWaitingClient(reject, startTime);
116
+ reject(new CommunicationError_js_1.CommunicationError(communicationErrorCodes_js_1.COMMUNICATION_ERROR_CODES.CONNECTION_TIMEOUT, 503, {
117
+ message: `Connection acquisition timeout after ${acquireTimeout}ms`,
118
+ pool: this.name,
119
+ waitingClients: this.waitingClients,
120
+ activeConnections: this.activeConnections,
121
+ }));
122
+ }, acquireTimeout);
123
+ this.waitingQueue.push({
124
+ resolve: (acquisition) => {
125
+ clearTimeout(timer);
126
+ resolve(acquisition);
127
+ },
128
+ reject: (error) => {
129
+ clearTimeout(timer);
130
+ reject(error);
131
+ },
132
+ timeout: timer,
133
+ startTime,
134
+ });
135
+ this.waitingClients++;
136
+ });
137
+ }
138
+ /**
139
+ * Get or create a connection
140
+ * @returns Connection or null if cannot create
141
+ */
142
+ async getOrCreateConnection() {
143
+ // Try to get from idle queue
144
+ while (this.idleConnectionsQueue.length > 0) {
145
+ const connection = this.idleConnectionsQueue.shift();
146
+ if (await this.validateConnection(connection)) {
147
+ return connection;
148
+ }
149
+ else {
150
+ await this.destroyConnection(connection);
151
+ }
152
+ }
153
+ // Create new connection if under limit
154
+ if (this.totalConnections < (this.config.maxConnections || 10)) {
155
+ try {
156
+ const connection = await this.createConnection();
157
+ this.pool.add(connection);
158
+ this.totalConnections++;
159
+ return connection;
160
+ }
161
+ catch (error) {
162
+ this.stats.totalErrors++;
163
+ return null;
164
+ }
165
+ }
166
+ return null;
167
+ }
168
+ /**
169
+ * Validate a connection
170
+ * @param connection Connection to validate
171
+ * @returns True if connection is valid
172
+ */
173
+ async validateConnection(connection) {
174
+ try {
175
+ const isValid = await this.validateConnectionFn(connection);
176
+ if (!isValid) {
177
+ await this.destroyConnection(connection);
178
+ return false;
179
+ }
180
+ return isValid;
181
+ }
182
+ catch (error) {
183
+ await this.destroyConnection(connection);
184
+ return false;
185
+ }
186
+ }
187
+ /**
188
+ * Release a connection back to the pool
189
+ * @param connection Connection to release
190
+ */
191
+ async release(connection) {
192
+ // Remove from active connections
193
+ this.activeConnectionsSet.delete(connection);
194
+ this.activeConnections--;
195
+ // Validate connection before returning to pool
196
+ if (await this.validateConnection(connection)) {
197
+ // Reset connection state
198
+ await connection.reset();
199
+ // Add to idle queue
200
+ this.idleConnectionsQueue.push(connection);
201
+ this.idleConnections++;
202
+ // Update connection stats
203
+ this.updateConnectionStats(connection, true);
204
+ // Notify waiting clients
205
+ this.notifyWaitingClients();
206
+ }
207
+ else {
208
+ // Destroy invalid connection
209
+ await this.destroyConnection(connection);
210
+ }
211
+ this.stats.totalReleases++;
212
+ }
213
+ /**
214
+ * Destroy a connection (remove from pool)
215
+ * @param connection Connection to destroy
216
+ */
217
+ async destroy(connection) {
218
+ await this.destroyConnection(connection);
219
+ }
220
+ /**
221
+ * Destroy a connection (internal)
222
+ * @param connection Connection to destroy
223
+ */
224
+ async destroyConnection(connection) {
225
+ try {
226
+ await connection.close();
227
+ }
228
+ catch (error) {
229
+ // Ignore close errors
230
+ }
231
+ // Remove from all collections
232
+ this.pool.delete(connection);
233
+ this.activeConnectionsSet.delete(connection);
234
+ const idleIndex = this.idleConnectionsQueue.indexOf(connection);
235
+ if (idleIndex !== -1) {
236
+ this.idleConnectionsQueue.splice(idleIndex, 1);
237
+ this.idleConnections--;
238
+ }
239
+ this.totalConnections--;
240
+ this.stats.totalDestructions++;
241
+ // Remove from stats
242
+ this.stats.connectionStats.delete(connection.id);
243
+ }
244
+ /**
245
+ * Execute a function with a connection from the pool
246
+ * @param fn Function to execute with connection
247
+ * @param timeout Operation timeout in milliseconds
248
+ * @returns Promise resolving to function result
249
+ */
250
+ async withConnection(fn, timeout) {
251
+ const acquisition = await this.acquire(timeout);
252
+ try {
253
+ const result = await fn(acquisition.connection);
254
+ return result;
255
+ }
256
+ finally {
257
+ await this.release(acquisition.connection);
258
+ }
259
+ }
260
+ /**
261
+ * Record connection acquisition
262
+ * @param startTime Acquisition start time
263
+ * @param connection Acquired connection
264
+ */
265
+ recordAcquisition(startTime, connection) {
266
+ const waitTime = Date.now() - startTime;
267
+ // Update connection stats
268
+ const connStats = this.stats.connectionStats.get(connection.id) || {
269
+ createdAt: connection.createdAt,
270
+ lastUsedAt: Date.now(),
271
+ usageCount: 0,
272
+ totalUsageTime: 0,
273
+ isHealthy: connection.isHealthy(),
274
+ };
275
+ connStats.usageCount++;
276
+ connStats.lastUsedAt = Date.now();
277
+ this.stats.connectionStats.set(connection.id, connStats);
278
+ // Update pool stats
279
+ this.stats.totalAcquisitions++;
280
+ this.stats.totalAcquisitionTime += waitTime;
281
+ this.stats.maxAcquisitionTime = Math.max(this.stats.maxAcquisitionTime, waitTime);
282
+ // Update pool state
283
+ const idleIndex = this.idleConnectionsQueue.indexOf(connection);
284
+ if (idleIndex !== -1) {
285
+ this.idleConnectionsQueue.splice(idleIndex, 1);
286
+ this.idleConnections--;
287
+ }
288
+ this.activeConnectionsSet.add(connection);
289
+ this.activeConnections++;
290
+ }
291
+ /**
292
+ * Create acquisition result
293
+ * @param connection Acquired connection
294
+ * @param waitTime Wait time in milliseconds
295
+ * @returns Connection acquisition result
296
+ */
297
+ createAcquisitionResult(connection, waitTime) {
298
+ return {
299
+ connection,
300
+ timestamp: Date.now(),
301
+ waitTime,
302
+ poolStats: {
303
+ totalConnections: this.totalConnections,
304
+ activeConnections: this.activeConnections,
305
+ idleConnections: this.idleConnections,
306
+ waitingClients: this.waitingClients,
307
+ },
308
+ };
309
+ }
310
+ /**
311
+ * Update connection statistics
312
+ * @param connection Connection
313
+ * @param released Whether connection was released
314
+ */
315
+ updateConnectionStats(connection, released) {
316
+ const connStats = this.stats.connectionStats.get(connection.id);
317
+ if (connStats && released) {
318
+ const usageTime = Date.now() - connStats.lastUsedAt;
319
+ connStats.totalUsageTime += usageTime;
320
+ connStats.isHealthy = connection.isHealthy();
321
+ this.stats.connectionStats.set(connection.id, connStats);
322
+ }
323
+ }
324
+ /**
325
+ * Remove waiting client from queue
326
+ * @param reject Reject function
327
+ * @param startTime Start time
328
+ */
329
+ removeWaitingClient(reject, startTime) {
330
+ const index = this.waitingQueue.findIndex(client => client.reject === reject);
331
+ if (index !== -1) {
332
+ this.waitingQueue.splice(index, 1);
333
+ this.waitingClients--;
334
+ }
335
+ }
336
+ /**
337
+ * Notify waiting clients
338
+ */
339
+ async notifyWaitingClients() {
340
+ while (this.waitingQueue.length > 0 && this.idleConnectionsQueue.length > 0) {
341
+ const connection = this.idleConnectionsQueue.shift();
342
+ if (!connection)
343
+ break;
344
+ if (await this.validateConnection(connection)) {
345
+ const client = this.waitingQueue.shift();
346
+ if (!client) {
347
+ this.idleConnectionsQueue.unshift(connection);
348
+ break;
349
+ }
350
+ this.waitingClients--;
351
+ clearTimeout(client.timeout);
352
+ const waitTime = Date.now() - client.startTime;
353
+ this.recordAcquisition(client.startTime, connection);
354
+ client.resolve(this.createAcquisitionResult(connection, waitTime));
355
+ }
356
+ else {
357
+ await this.destroyConnection(connection);
358
+ }
359
+ }
360
+ }
361
+ /**
362
+ * Clean up idle connections
363
+ */
364
+ async cleanupIdleConnections() {
365
+ const now = Date.now();
366
+ const maxIdleTime = this.config.idleTimeout || 60000;
367
+ for (let i = this.idleConnectionsQueue.length - 1; i >= 0; i--) {
368
+ const connection = this.idleConnectionsQueue[i];
369
+ const idleTime = now - connection.lastUsedAt;
370
+ // Check idle timeout
371
+ if (idleTime > maxIdleTime) {
372
+ this.idleConnectionsQueue.splice(i, 1);
373
+ this.idleConnections--;
374
+ await this.destroyConnection(connection);
375
+ continue;
376
+ }
377
+ // Check max lifetime
378
+ if (this.config.maxLifetime) {
379
+ const age = now - connection.createdAt;
380
+ if (age > this.config.maxLifetime) {
381
+ this.idleConnectionsQueue.splice(i, 1);
382
+ this.idleConnections--;
383
+ await this.destroyConnection(connection);
384
+ }
385
+ }
386
+ }
387
+ }
388
+ /**
389
+ * Check pool health
390
+ */
391
+ async checkPoolHealth() {
392
+ try {
393
+ // Validate all idle connections
394
+ for (const connection of this.idleConnectionsQueue) {
395
+ if (!(await this.validateConnection(connection))) {
396
+ const index = this.idleConnectionsQueue.indexOf(connection);
397
+ if (index !== -1) {
398
+ this.idleConnectionsQueue.splice(index, 1);
399
+ this.idleConnections--;
400
+ }
401
+ }
402
+ }
403
+ // Check if pool meets minimum connections
404
+ if (this.config.minConnections && this.totalConnections < this.config.minConnections) {
405
+ await this.warmupPool();
406
+ }
407
+ this.isHealthy = true;
408
+ }
409
+ catch (error) {
410
+ this.isHealthy = false;
411
+ this.stats.totalErrors++;
412
+ }
413
+ }
414
+ /**
415
+ * Drain the pool (gracefully close all connections)
416
+ * @param force Force immediate drain
417
+ */
418
+ async drain(force) {
419
+ // Stop accepting new requests
420
+ this.isHealthy = false;
421
+ // Clear intervals
422
+ if (this.cleanupInterval) {
423
+ clearInterval(this.cleanupInterval);
424
+ this.cleanupInterval = undefined;
425
+ }
426
+ if (this.healthCheckInterval) {
427
+ clearInterval(this.healthCheckInterval);
428
+ this.healthCheckInterval = undefined;
429
+ }
430
+ // Wait for active connections to finish (if not forced)
431
+ if (!force) {
432
+ const maxWaitTime = 30000; // 30 seconds max wait
433
+ const startTime = Date.now();
434
+ while (this.activeConnections > 0 && (Date.now() - startTime) < maxWaitTime) {
435
+ await new Promise(resolve => setTimeout(resolve, 100));
436
+ }
437
+ }
438
+ // Close all connections
439
+ const closePromises = Array.from(this.pool).map(conn => conn.close());
440
+ await Promise.allSettled(closePromises);
441
+ // Clear all collections
442
+ this.pool.clear();
443
+ this.activeConnectionsSet.clear();
444
+ this.idleConnectionsQueue.length = 0;
445
+ this.totalConnections = 0;
446
+ this.activeConnections = 0;
447
+ this.idleConnections = 0;
448
+ // Clear waiting queue
449
+ for (const client of this.waitingQueue) {
450
+ clearTimeout(client.timeout);
451
+ client.reject(new CommunicationError_js_1.CommunicationError(communicationErrorCodes_js_1.COMMUNICATION_ERROR_CODES.CONNECTION_ERROR, 503, { message: 'Pool is draining' }));
452
+ }
453
+ this.waitingQueue.length = 0;
454
+ this.waitingClients = 0;
455
+ }
456
+ /**
457
+ * Clear the pool (force close all connections)
458
+ */
459
+ async clear() {
460
+ await this.drain(true);
461
+ }
462
+ /**
463
+ * Health check for the pool
464
+ */
465
+ async healthCheck() {
466
+ const healthy = this.isHealthy && this.totalConnections > 0;
467
+ return {
468
+ healthy,
469
+ message: healthy ? 'Connection pool is healthy' : 'Connection pool is not healthy',
470
+ details: {
471
+ name: this.name,
472
+ totalConnections: this.totalConnections,
473
+ activeConnections: this.activeConnections,
474
+ idleConnections: this.idleConnections,
475
+ waitingClients: this.waitingClients,
476
+ config: this.config,
477
+ statistics: this.getStats(),
478
+ },
479
+ };
480
+ }
481
+ /**
482
+ * Get pool statistics
483
+ */
484
+ getStats() {
485
+ const connectionStats = Array.from(this.stats.connectionStats.entries()).map(([id, stats]) => ({
486
+ id,
487
+ createdAt: stats.createdAt,
488
+ lastUsedAt: stats.lastUsedAt,
489
+ usageCount: stats.usageCount,
490
+ isHealthy: stats.isHealthy,
491
+ }));
492
+ const acquisitionTimeAverage = this.stats.totalAcquisitions > 0
493
+ ? this.stats.totalAcquisitionTime / this.stats.totalAcquisitions
494
+ : 0;
495
+ const poolUtilization = this.config.maxConnections
496
+ ? this.activeConnections / this.config.maxConnections
497
+ : 0;
498
+ return {
499
+ totalConnections: this.totalConnections,
500
+ activeConnections: this.activeConnections,
501
+ idleConnections: this.idleConnections,
502
+ waitingClients: this.waitingClients,
503
+ totalAcquisitions: this.stats.totalAcquisitions,
504
+ totalReleases: this.stats.totalReleases,
505
+ totalDestructions: this.stats.totalDestructions,
506
+ totalErrors: this.stats.totalErrors,
507
+ acquisitionTimeAverage,
508
+ acquisitionTimeMax: this.stats.maxAcquisitionTime,
509
+ poolUtilization,
510
+ connectionStats,
511
+ };
512
+ }
513
+ /**
514
+ * Reset pool statistics
515
+ */
516
+ resetStats() {
517
+ this.stats = {
518
+ totalAcquisitions: 0,
519
+ totalReleases: 0,
520
+ totalDestructions: 0,
521
+ totalErrors: 0,
522
+ totalAcquisitionTime: 0,
523
+ maxAcquisitionTime: 0,
524
+ connectionStats: new Map(),
525
+ };
526
+ }
527
+ /**
528
+ * Update pool configuration
529
+ * @param config New configuration
530
+ */
531
+ updateConfig(config) {
532
+ this.config = { ...this.config, ...config };
533
+ // Restart intervals if needed
534
+ if (this.cleanupInterval) {
535
+ clearInterval(this.cleanupInterval);
536
+ }
537
+ if (this.healthCheckInterval) {
538
+ clearInterval(this.healthCheckInterval);
539
+ }
540
+ this.initialize();
541
+ }
542
+ }
543
+ exports.BaseConnectionPool = BaseConnectionPool;