connection_pool.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.ConnectionPool = exports.PoolState = void 0;
  4. const timers_1 = require("timers");
  5. const constants_1 = require("../constants");
  6. const error_1 = require("../error");
  7. const mongo_types_1 = require("../mongo_types");
  8. const timeout_1 = require("../timeout");
  9. const utils_1 = require("../utils");
  10. const connect_1 = require("./connect");
  11. const connection_1 = require("./connection");
  12. const connection_pool_events_1 = require("./connection_pool_events");
  13. const errors_1 = require("./errors");
  14. const metrics_1 = require("./metrics");
  15. /** @internal */
  16. exports.PoolState = Object.freeze({
  17. paused: 'paused',
  18. ready: 'ready',
  19. closed: 'closed'
  20. });
  21. /**
  22. * A pool of connections which dynamically resizes, and emit events related to pool activity
  23. * @internal
  24. */
  25. class ConnectionPool extends mongo_types_1.TypedEventEmitter {
  26. constructor(server, options) {
  27. super();
  28. this.on('error', utils_1.noop);
  29. this.options = Object.freeze({
  30. connectionType: connection_1.Connection,
  31. ...options,
  32. maxPoolSize: options.maxPoolSize ?? 100,
  33. minPoolSize: options.minPoolSize ?? 0,
  34. maxConnecting: options.maxConnecting ?? 2,
  35. maxIdleTimeMS: options.maxIdleTimeMS ?? 0,
  36. waitQueueTimeoutMS: options.waitQueueTimeoutMS ?? 0,
  37. minPoolSizeCheckFrequencyMS: options.minPoolSizeCheckFrequencyMS ?? 100,
  38. autoEncrypter: options.autoEncrypter
  39. });
  40. if (this.options.minPoolSize > this.options.maxPoolSize) {
  41. throw new error_1.MongoInvalidArgumentError('Connection pool minimum size must not be greater than maximum pool size');
  42. }
  43. this.poolState = exports.PoolState.paused;
  44. this.server = server;
  45. this.connections = new utils_1.List();
  46. this.pending = 0;
  47. this.checkedOut = new Set();
  48. this.minPoolSizeTimer = undefined;
  49. this.generation = 0;
  50. this.serviceGenerations = new Map();
  51. this.connectionCounter = (0, utils_1.makeCounter)(1);
  52. this.cancellationToken = new mongo_types_1.CancellationToken();
  53. this.cancellationToken.setMaxListeners(Infinity);
  54. this.waitQueue = new utils_1.List();
  55. this.metrics = new metrics_1.ConnectionPoolMetrics();
  56. this.processingWaitQueue = false;
  57. this.mongoLogger = this.server.topology.client?.mongoLogger;
  58. this.component = 'connection';
  59. process.nextTick(() => {
  60. this.emitAndLog(ConnectionPool.CONNECTION_POOL_CREATED, new connection_pool_events_1.ConnectionPoolCreatedEvent(this));
  61. });
  62. }
  63. /** The address of the endpoint the pool is connected to */
  64. get address() {
  65. return this.options.hostAddress.toString();
  66. }
  67. /**
  68. * Check if the pool has been closed
  69. *
  70. * TODO(NODE-3263): We can remove this property once shell no longer needs it
  71. */
  72. get closed() {
  73. return this.poolState === exports.PoolState.closed;
  74. }
  75. /** An integer expressing how many total connections (available + pending + in use) the pool currently has */
  76. get totalConnectionCount() {
  77. return (this.availableConnectionCount + this.pendingConnectionCount + this.currentCheckedOutCount);
  78. }
  79. /** An integer expressing how many connections are currently available in the pool. */
  80. get availableConnectionCount() {
  81. return this.connections.length;
  82. }
  83. get pendingConnectionCount() {
  84. return this.pending;
  85. }
  86. get currentCheckedOutCount() {
  87. return this.checkedOut.size;
  88. }
  89. get waitQueueSize() {
  90. return this.waitQueue.length;
  91. }
  92. get loadBalanced() {
  93. return this.options.loadBalanced;
  94. }
  95. get serverError() {
  96. return this.server.description.error;
  97. }
  98. /**
  99. * This is exposed ONLY for use in mongosh, to enable
  100. * killing all connections if a user quits the shell with
  101. * operations in progress.
  102. *
  103. * This property may be removed as a part of NODE-3263.
  104. */
  105. get checkedOutConnections() {
  106. return this.checkedOut;
  107. }
  108. /**
  109. * Get the metrics information for the pool when a wait queue timeout occurs.
  110. */
  111. waitQueueErrorMetrics() {
  112. return this.metrics.info(this.options.maxPoolSize);
  113. }
  114. /**
  115. * Set the pool state to "ready"
  116. */
  117. ready() {
  118. if (this.poolState !== exports.PoolState.paused) {
  119. return;
  120. }
  121. this.poolState = exports.PoolState.ready;
  122. this.emitAndLog(ConnectionPool.CONNECTION_POOL_READY, new connection_pool_events_1.ConnectionPoolReadyEvent(this));
  123. (0, timers_1.clearTimeout)(this.minPoolSizeTimer);
  124. this.ensureMinPoolSize();
  125. }
  126. /**
  127. * Check a connection out of this pool. The connection will continue to be tracked, but no reference to it
  128. * will be held by the pool. This means that if a connection is checked out it MUST be checked back in or
  129. * explicitly destroyed by the new owner.
  130. */
  131. async checkOut(options) {
  132. const checkoutTime = (0, utils_1.now)();
  133. this.emitAndLog(ConnectionPool.CONNECTION_CHECK_OUT_STARTED, new connection_pool_events_1.ConnectionCheckOutStartedEvent(this));
  134. const { promise, resolve, reject } = (0, utils_1.promiseWithResolvers)();
  135. const timeout = options.timeoutContext.connectionCheckoutTimeout;
  136. const waitQueueMember = {
  137. resolve,
  138. reject,
  139. cancelled: false,
  140. checkoutTime
  141. };
  142. const abortListener = (0, utils_1.addAbortListener)(options.signal, function () {
  143. waitQueueMember.cancelled = true;
  144. reject(this.reason);
  145. });
  146. this.waitQueue.push(waitQueueMember);
  147. process.nextTick(() => this.processWaitQueue());
  148. try {
  149. timeout?.throwIfExpired();
  150. return await (timeout ? Promise.race([promise, timeout]) : promise);
  151. }
  152. catch (error) {
  153. if (timeout_1.TimeoutError.is(error)) {
  154. timeout?.clear();
  155. waitQueueMember.cancelled = true;
  156. this.emitAndLog(ConnectionPool.CONNECTION_CHECK_OUT_FAILED, new connection_pool_events_1.ConnectionCheckOutFailedEvent(this, 'timeout', waitQueueMember.checkoutTime));
  157. const timeoutError = new errors_1.WaitQueueTimeoutError(this.loadBalanced
  158. ? this.waitQueueErrorMetrics()
  159. : 'Timed out while checking out a connection from connection pool', this.address);
  160. if (options.timeoutContext.csotEnabled()) {
  161. throw new error_1.MongoOperationTimeoutError('Timed out during connection checkout', {
  162. cause: timeoutError
  163. });
  164. }
  165. throw timeoutError;
  166. }
  167. throw error;
  168. }
  169. finally {
  170. abortListener?.[utils_1.kDispose]();
  171. timeout?.clear();
  172. }
  173. }
  174. /**
  175. * Check a connection into the pool.
  176. *
  177. * @param connection - The connection to check in
  178. */
  179. checkIn(connection) {
  180. if (!this.checkedOut.has(connection)) {
  181. return;
  182. }
  183. const poolClosed = this.closed;
  184. const stale = this.connectionIsStale(connection);
  185. const willDestroy = !!(poolClosed || stale || connection.closed);
  186. if (!willDestroy) {
  187. connection.markAvailable();
  188. this.connections.unshift(connection);
  189. }
  190. this.checkedOut.delete(connection);
  191. this.emitAndLog(ConnectionPool.CONNECTION_CHECKED_IN, new connection_pool_events_1.ConnectionCheckedInEvent(this, connection));
  192. if (willDestroy) {
  193. const reason = connection.closed ? 'error' : poolClosed ? 'poolClosed' : 'stale';
  194. this.destroyConnection(connection, reason);
  195. }
  196. process.nextTick(() => this.processWaitQueue());
  197. }
  198. /**
  199. * Clear the pool
  200. *
  201. * Pool reset is handled by incrementing the pool's generation count. Any existing connection of a
  202. * previous generation will eventually be pruned during subsequent checkouts.
  203. */
  204. clear(options = {}) {
  205. if (this.closed) {
  206. return;
  207. }
  208. // handle load balanced case
  209. if (this.loadBalanced) {
  210. const { serviceId } = options;
  211. if (!serviceId) {
  212. throw new error_1.MongoRuntimeError('ConnectionPool.clear() called in load balanced mode with no serviceId.');
  213. }
  214. const sid = serviceId.toHexString();
  215. const generation = this.serviceGenerations.get(sid);
  216. // Only need to worry if the generation exists, since it should
  217. // always be there but typescript needs the check.
  218. if (generation == null) {
  219. throw new error_1.MongoRuntimeError('Service generations are required in load balancer mode.');
  220. }
  221. else {
  222. // Increment the generation for the service id.
  223. this.serviceGenerations.set(sid, generation + 1);
  224. }
  225. this.emitAndLog(ConnectionPool.CONNECTION_POOL_CLEARED, new connection_pool_events_1.ConnectionPoolClearedEvent(this, { serviceId }));
  226. return;
  227. }
  228. // handle non load-balanced case
  229. const interruptInUseConnections = options.interruptInUseConnections ?? false;
  230. const oldGeneration = this.generation;
  231. this.generation += 1;
  232. const alreadyPaused = this.poolState === exports.PoolState.paused;
  233. this.poolState = exports.PoolState.paused;
  234. this.clearMinPoolSizeTimer();
  235. if (!alreadyPaused) {
  236. this.emitAndLog(ConnectionPool.CONNECTION_POOL_CLEARED, new connection_pool_events_1.ConnectionPoolClearedEvent(this, {
  237. interruptInUseConnections
  238. }));
  239. }
  240. if (interruptInUseConnections) {
  241. process.nextTick(() => this.interruptInUseConnections(oldGeneration));
  242. }
  243. this.processWaitQueue();
  244. }
  245. /**
  246. * Closes all stale in-use connections in the pool with a resumable PoolClearedOnNetworkError.
  247. *
  248. * Only connections where `connection.generation <= minGeneration` are killed.
  249. */
  250. interruptInUseConnections(minGeneration) {
  251. for (const connection of this.checkedOut) {
  252. if (connection.generation <= minGeneration) {
  253. connection.onError(new errors_1.PoolClearedOnNetworkError(this));
  254. }
  255. }
  256. }
  257. /** For MongoClient.close() procedures */
  258. closeCheckedOutConnections() {
  259. for (const conn of this.checkedOut) {
  260. conn.onError(new error_1.MongoClientClosedError());
  261. }
  262. }
  263. /** Close the pool */
  264. close() {
  265. if (this.closed) {
  266. return;
  267. }
  268. // immediately cancel any in-flight connections
  269. this.cancellationToken.emit('cancel');
  270. // end the connection counter
  271. if (typeof this.connectionCounter.return === 'function') {
  272. this.connectionCounter.return(undefined);
  273. }
  274. this.poolState = exports.PoolState.closed;
  275. this.clearMinPoolSizeTimer();
  276. this.processWaitQueue();
  277. for (const conn of this.connections) {
  278. this.emitAndLog(ConnectionPool.CONNECTION_CLOSED, new connection_pool_events_1.ConnectionClosedEvent(this, conn, 'poolClosed'));
  279. conn.destroy();
  280. }
  281. this.connections.clear();
  282. this.emitAndLog(ConnectionPool.CONNECTION_POOL_CLOSED, new connection_pool_events_1.ConnectionPoolClosedEvent(this));
  283. }
  284. /**
  285. * @internal
  286. * Reauthenticate a connection
  287. */
  288. async reauthenticate(connection) {
  289. const authContext = connection.authContext;
  290. if (!authContext) {
  291. throw new error_1.MongoRuntimeError('No auth context found on connection.');
  292. }
  293. const credentials = authContext.credentials;
  294. if (!credentials) {
  295. throw new error_1.MongoMissingCredentialsError('Connection is missing credentials when asked to reauthenticate');
  296. }
  297. const resolvedCredentials = credentials.resolveAuthMechanism(connection.hello);
  298. const provider = this.server.topology.client.s.authProviders.getOrCreateProvider(resolvedCredentials.mechanism, resolvedCredentials.mechanismProperties);
  299. if (!provider) {
  300. throw new error_1.MongoMissingCredentialsError(`Reauthenticate failed due to no auth provider for ${credentials.mechanism}`);
  301. }
  302. await provider.reauth(authContext);
  303. return;
  304. }
  305. /** Clear the min pool size timer */
  306. clearMinPoolSizeTimer() {
  307. const minPoolSizeTimer = this.minPoolSizeTimer;
  308. if (minPoolSizeTimer) {
  309. (0, timers_1.clearTimeout)(minPoolSizeTimer);
  310. }
  311. }
  312. destroyConnection(connection, reason) {
  313. this.emitAndLog(ConnectionPool.CONNECTION_CLOSED, new connection_pool_events_1.ConnectionClosedEvent(this, connection, reason));
  314. // destroy the connection
  315. connection.destroy();
  316. }
  317. connectionIsStale(connection) {
  318. const serviceId = connection.serviceId;
  319. if (this.loadBalanced && serviceId) {
  320. const sid = serviceId.toHexString();
  321. const generation = this.serviceGenerations.get(sid);
  322. return connection.generation !== generation;
  323. }
  324. return connection.generation !== this.generation;
  325. }
  326. connectionIsIdle(connection) {
  327. return !!(this.options.maxIdleTimeMS && connection.idleTime > this.options.maxIdleTimeMS);
  328. }
  329. /**
  330. * Destroys a connection if the connection is perished.
  331. *
  332. * @returns `true` if the connection was destroyed, `false` otherwise.
  333. */
  334. destroyConnectionIfPerished(connection) {
  335. const isStale = this.connectionIsStale(connection);
  336. const isIdle = this.connectionIsIdle(connection);
  337. if (!isStale && !isIdle && !connection.closed) {
  338. return false;
  339. }
  340. const reason = connection.closed ? 'error' : isStale ? 'stale' : 'idle';
  341. this.destroyConnection(connection, reason);
  342. return true;
  343. }
  344. createConnection(callback) {
  345. // Note that metadata and extendedMetadata may have changed on the client but have
  346. // been frozen here, so we pull the extendedMetadata promise always from the client
  347. // no mattter what options were set at the construction of the pool.
  348. const connectOptions = {
  349. ...this.options,
  350. id: this.connectionCounter.next().value,
  351. generation: this.generation,
  352. cancellationToken: this.cancellationToken,
  353. mongoLogger: this.mongoLogger,
  354. authProviders: this.server.topology.client.s.authProviders,
  355. extendedMetadata: this.server.topology.client.options.extendedMetadata
  356. };
  357. this.pending++;
  358. // This is our version of a "virtual" no-I/O connection as the spec requires
  359. const connectionCreatedTime = (0, utils_1.now)();
  360. this.emitAndLog(ConnectionPool.CONNECTION_CREATED, new connection_pool_events_1.ConnectionCreatedEvent(this, { id: connectOptions.id }));
  361. (0, connect_1.connect)(connectOptions).then(connection => {
  362. // The pool might have closed since we started trying to create a connection
  363. if (this.poolState !== exports.PoolState.ready) {
  364. this.pending--;
  365. connection.destroy();
  366. callback(this.closed ? new errors_1.PoolClosedError(this) : new errors_1.PoolClearedError(this));
  367. return;
  368. }
  369. // forward all events from the connection to the pool
  370. for (const event of [...constants_1.APM_EVENTS, connection_1.Connection.CLUSTER_TIME_RECEIVED]) {
  371. connection.on(event, (e) => this.emit(event, e));
  372. }
  373. if (this.loadBalanced) {
  374. connection.on(connection_1.Connection.PINNED, pinType => this.metrics.markPinned(pinType));
  375. connection.on(connection_1.Connection.UNPINNED, pinType => this.metrics.markUnpinned(pinType));
  376. const serviceId = connection.serviceId;
  377. if (serviceId) {
  378. let generation;
  379. const sid = serviceId.toHexString();
  380. if ((generation = this.serviceGenerations.get(sid))) {
  381. connection.generation = generation;
  382. }
  383. else {
  384. this.serviceGenerations.set(sid, 0);
  385. connection.generation = 0;
  386. }
  387. }
  388. }
  389. connection.markAvailable();
  390. this.emitAndLog(ConnectionPool.CONNECTION_READY, new connection_pool_events_1.ConnectionReadyEvent(this, connection, connectionCreatedTime));
  391. this.pending--;
  392. callback(undefined, connection);
  393. }, error => {
  394. this.pending--;
  395. this.server.handleError(error);
  396. this.emitAndLog(ConnectionPool.CONNECTION_CLOSED, new connection_pool_events_1.ConnectionClosedEvent(this, { id: connectOptions.id, serviceId: undefined }, 'error',
  397. // TODO(NODE-5192): Remove this cast
  398. error));
  399. if (error instanceof error_1.MongoNetworkError || error instanceof error_1.MongoServerError) {
  400. error.connectionGeneration = connectOptions.generation;
  401. }
  402. callback(error ?? new error_1.MongoRuntimeError('Connection creation failed without error'));
  403. });
  404. }
  405. ensureMinPoolSize() {
  406. const minPoolSize = this.options.minPoolSize;
  407. if (this.poolState !== exports.PoolState.ready) {
  408. return;
  409. }
  410. this.connections.prune(connection => this.destroyConnectionIfPerished(connection));
  411. if (this.totalConnectionCount < minPoolSize &&
  412. this.pendingConnectionCount < this.options.maxConnecting) {
  413. // NOTE: ensureMinPoolSize should not try to get all the pending
  414. // connection permits because that potentially delays the availability of
  415. // the connection to a checkout request
  416. this.createConnection((err, connection) => {
  417. if (!err && connection) {
  418. this.connections.push(connection);
  419. process.nextTick(() => this.processWaitQueue());
  420. }
  421. if (this.poolState === exports.PoolState.ready) {
  422. (0, timers_1.clearTimeout)(this.minPoolSizeTimer);
  423. this.minPoolSizeTimer = (0, timers_1.setTimeout)(() => this.ensureMinPoolSize(), this.options.minPoolSizeCheckFrequencyMS);
  424. }
  425. });
  426. }
  427. else {
  428. (0, timers_1.clearTimeout)(this.minPoolSizeTimer);
  429. this.minPoolSizeTimer = (0, timers_1.setTimeout)(() => this.ensureMinPoolSize(), this.options.minPoolSizeCheckFrequencyMS);
  430. }
  431. }
  432. processWaitQueue() {
  433. if (this.processingWaitQueue) {
  434. return;
  435. }
  436. this.processingWaitQueue = true;
  437. while (this.waitQueueSize) {
  438. const waitQueueMember = this.waitQueue.first();
  439. if (!waitQueueMember) {
  440. this.waitQueue.shift();
  441. continue;
  442. }
  443. if (waitQueueMember.cancelled) {
  444. this.waitQueue.shift();
  445. continue;
  446. }
  447. if (this.poolState !== exports.PoolState.ready) {
  448. const reason = this.closed ? 'poolClosed' : 'connectionError';
  449. const error = this.closed ? new errors_1.PoolClosedError(this) : new errors_1.PoolClearedError(this);
  450. this.emitAndLog(ConnectionPool.CONNECTION_CHECK_OUT_FAILED, new connection_pool_events_1.ConnectionCheckOutFailedEvent(this, reason, waitQueueMember.checkoutTime, error));
  451. this.waitQueue.shift();
  452. waitQueueMember.reject(error);
  453. continue;
  454. }
  455. if (!this.availableConnectionCount) {
  456. break;
  457. }
  458. const connection = this.connections.shift();
  459. if (!connection) {
  460. break;
  461. }
  462. if (!this.destroyConnectionIfPerished(connection)) {
  463. this.checkedOut.add(connection);
  464. this.emitAndLog(ConnectionPool.CONNECTION_CHECKED_OUT, new connection_pool_events_1.ConnectionCheckedOutEvent(this, connection, waitQueueMember.checkoutTime));
  465. this.waitQueue.shift();
  466. waitQueueMember.resolve(connection);
  467. }
  468. }
  469. const { maxPoolSize, maxConnecting } = this.options;
  470. while (this.waitQueueSize > 0 &&
  471. this.pendingConnectionCount < maxConnecting &&
  472. (maxPoolSize === 0 || this.totalConnectionCount < maxPoolSize)) {
  473. const waitQueueMember = this.waitQueue.shift();
  474. if (!waitQueueMember || waitQueueMember.cancelled) {
  475. continue;
  476. }
  477. this.createConnection((err, connection) => {
  478. if (waitQueueMember.cancelled) {
  479. if (!err && connection) {
  480. this.connections.push(connection);
  481. }
  482. }
  483. else {
  484. if (err) {
  485. this.emitAndLog(ConnectionPool.CONNECTION_CHECK_OUT_FAILED,
  486. // TODO(NODE-5192): Remove this cast
  487. new connection_pool_events_1.ConnectionCheckOutFailedEvent(this, 'connectionError', waitQueueMember.checkoutTime, err));
  488. waitQueueMember.reject(err);
  489. }
  490. else if (connection) {
  491. this.checkedOut.add(connection);
  492. this.emitAndLog(ConnectionPool.CONNECTION_CHECKED_OUT, new connection_pool_events_1.ConnectionCheckedOutEvent(this, connection, waitQueueMember.checkoutTime));
  493. waitQueueMember.resolve(connection);
  494. }
  495. }
  496. process.nextTick(() => this.processWaitQueue());
  497. });
  498. }
  499. this.processingWaitQueue = false;
  500. }
  501. }
  502. exports.ConnectionPool = ConnectionPool;
  503. /**
  504. * Emitted when the connection pool is created.
  505. * @event
  506. */
  507. ConnectionPool.CONNECTION_POOL_CREATED = constants_1.CONNECTION_POOL_CREATED;
  508. /**
  509. * Emitted once when the connection pool is closed
  510. * @event
  511. */
  512. ConnectionPool.CONNECTION_POOL_CLOSED = constants_1.CONNECTION_POOL_CLOSED;
  513. /**
  514. * Emitted each time the connection pool is cleared and it's generation incremented
  515. * @event
  516. */
  517. ConnectionPool.CONNECTION_POOL_CLEARED = constants_1.CONNECTION_POOL_CLEARED;
  518. /**
  519. * Emitted each time the connection pool is marked ready
  520. * @event
  521. */
  522. ConnectionPool.CONNECTION_POOL_READY = constants_1.CONNECTION_POOL_READY;
  523. /**
  524. * Emitted when a connection is created.
  525. * @event
  526. */
  527. ConnectionPool.CONNECTION_CREATED = constants_1.CONNECTION_CREATED;
  528. /**
  529. * Emitted when a connection becomes established, and is ready to use
  530. * @event
  531. */
  532. ConnectionPool.CONNECTION_READY = constants_1.CONNECTION_READY;
  533. /**
  534. * Emitted when a connection is closed
  535. * @event
  536. */
  537. ConnectionPool.CONNECTION_CLOSED = constants_1.CONNECTION_CLOSED;
  538. /**
  539. * Emitted when an attempt to check out a connection begins
  540. * @event
  541. */
  542. ConnectionPool.CONNECTION_CHECK_OUT_STARTED = constants_1.CONNECTION_CHECK_OUT_STARTED;
  543. /**
  544. * Emitted when an attempt to check out a connection fails
  545. * @event
  546. */
  547. ConnectionPool.CONNECTION_CHECK_OUT_FAILED = constants_1.CONNECTION_CHECK_OUT_FAILED;
  548. /**
  549. * Emitted each time a connection is successfully checked out of the connection pool
  550. * @event
  551. */
  552. ConnectionPool.CONNECTION_CHECKED_OUT = constants_1.CONNECTION_CHECKED_OUT;
  553. /**
  554. * Emitted each time a connection is successfully checked into the connection pool
  555. * @event
  556. */
  557. ConnectionPool.CONNECTION_CHECKED_IN = constants_1.CONNECTION_CHECKED_IN;
  558. //# sourceMappingURL=connection_pool.js.map