@ragestudio/scylla-odm 0.22.2 → 0.22.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.
Files changed (153) hide show
  1. package/batch/index.d.ts +3 -3
  2. package/batch/index.d.ts.map +1 -1
  3. package/client.d.ts +6 -5
  4. package/client.d.ts.map +1 -1
  5. package/client.js +7 -7
  6. package/client.js.map +1 -1
  7. package/cql_gen/create_table.d.ts +1 -1
  8. package/cql_gen/create_table.d.ts.map +1 -1
  9. package/document/index.d.ts +3 -3
  10. package/document/index.d.ts.map +1 -1
  11. package/driver/LICENSE.txt +177 -0
  12. package/driver/NOTICE.txt +67 -0
  13. package/driver/auth/index.d.ts +37 -0
  14. package/driver/auth/index.js +37 -0
  15. package/driver/auth/no-auth-provider.js +73 -0
  16. package/driver/auth/plain-text-auth-provider.js +81 -0
  17. package/driver/auth/provider.js +77 -0
  18. package/driver/client-options.js +442 -0
  19. package/driver/client.js +1267 -0
  20. package/driver/concurrent/index.d.ts +49 -0
  21. package/driver/concurrent/index.js +366 -0
  22. package/driver/connection.js +1034 -0
  23. package/driver/control-connection.js +1282 -0
  24. package/driver/encoder.js +2316 -0
  25. package/driver/errors.js +223 -0
  26. package/driver/execution-options.js +612 -0
  27. package/driver/execution-profile.js +274 -0
  28. package/driver/host-connection-pool.js +587 -0
  29. package/driver/host.js +699 -0
  30. package/driver/index.d.ts +387 -0
  31. package/driver/index.js +81 -0
  32. package/driver/mapping/cache.js +214 -0
  33. package/driver/mapping/doc-info-adapter.js +171 -0
  34. package/driver/mapping/index.d.ts +219 -0
  35. package/driver/mapping/index.js +57 -0
  36. package/driver/mapping/mapper.js +225 -0
  37. package/driver/mapping/mapping-handler.js +641 -0
  38. package/driver/mapping/model-batch-item.js +215 -0
  39. package/driver/mapping/model-batch-mapper.js +141 -0
  40. package/driver/mapping/model-mapper.js +315 -0
  41. package/driver/mapping/model-mapping-info.js +225 -0
  42. package/driver/mapping/object-selector.js +417 -0
  43. package/driver/mapping/q.js +156 -0
  44. package/driver/mapping/query-generator.js +556 -0
  45. package/driver/mapping/result-mapper.js +123 -0
  46. package/driver/mapping/result.js +139 -0
  47. package/driver/mapping/table-mappings.js +133 -0
  48. package/driver/mapping/tree.js +160 -0
  49. package/driver/metadata/aggregate.js +79 -0
  50. package/driver/metadata/client-state.js +119 -0
  51. package/driver/metadata/data-collection.js +182 -0
  52. package/driver/metadata/event-debouncer.js +174 -0
  53. package/driver/metadata/index.d.ts +276 -0
  54. package/driver/metadata/index.js +1156 -0
  55. package/driver/metadata/materialized-view.js +49 -0
  56. package/driver/metadata/schema-function.js +98 -0
  57. package/driver/metadata/schema-index.js +166 -0
  58. package/driver/metadata/schema-parser.js +1399 -0
  59. package/driver/metadata/table-metadata.js +77 -0
  60. package/driver/operation-state.js +206 -0
  61. package/driver/policies/address-resolution.js +145 -0
  62. package/driver/policies/index.d.ts +241 -0
  63. package/driver/policies/index.js +110 -0
  64. package/driver/policies/load-balancing.js +970 -0
  65. package/driver/policies/reconnection.js +166 -0
  66. package/driver/policies/retry.js +326 -0
  67. package/driver/policies/speculative-execution.js +150 -0
  68. package/driver/policies/timestamp-generation.js +176 -0
  69. package/driver/prepare-handler.js +347 -0
  70. package/driver/promise-utils.js +191 -0
  71. package/driver/readers.js +624 -0
  72. package/driver/request-execution.js +644 -0
  73. package/driver/request-handler.js +332 -0
  74. package/driver/requests.js +618 -0
  75. package/driver/stream-id-stack.js +209 -0
  76. package/driver/streams.js +745 -0
  77. package/driver/token.js +325 -0
  78. package/driver/tokenizer.js +631 -0
  79. package/driver/types/big-decimal.js +282 -0
  80. package/driver/types/duration.js +576 -0
  81. package/driver/types/index.d.ts +486 -0
  82. package/driver/types/index.js +733 -0
  83. package/driver/types/inet-address.js +262 -0
  84. package/driver/types/integer.js +818 -0
  85. package/driver/types/local-date.js +280 -0
  86. package/driver/types/local-time.js +299 -0
  87. package/driver/types/mutable-long.js +385 -0
  88. package/driver/types/protocol-version.js +391 -0
  89. package/driver/types/result-set.js +287 -0
  90. package/driver/types/result-stream.js +164 -0
  91. package/driver/types/row.js +85 -0
  92. package/driver/types/time-uuid.js +414 -0
  93. package/driver/types/tuple.js +103 -0
  94. package/driver/types/uuid.js +160 -0
  95. package/driver/types/vector.js +130 -0
  96. package/driver/types/version-number.js +153 -0
  97. package/driver/utils.js +1485 -0
  98. package/driver/writers.js +350 -0
  99. package/global.d.ts +1 -1
  100. package/global.d.ts.map +1 -1
  101. package/index.d.ts +6 -6
  102. package/index.d.ts.map +1 -1
  103. package/index.js +6 -6
  104. package/index.js.map +1 -1
  105. package/migrate/index.d.ts +1 -1
  106. package/migrate/index.d.ts.map +1 -1
  107. package/migrate/index.js +1 -1
  108. package/migrate/index.js.map +1 -1
  109. package/model/index.d.ts +6 -6
  110. package/model/index.d.ts.map +1 -1
  111. package/model/index.js +10 -10
  112. package/model/index.js.map +1 -1
  113. package/operations/countAll.d.ts +1 -1
  114. package/operations/countAll.d.ts.map +1 -1
  115. package/operations/delete.d.ts +3 -4
  116. package/operations/delete.d.ts.map +1 -1
  117. package/operations/delete.js +1 -1
  118. package/operations/delete.js.map +1 -1
  119. package/operations/find.d.ts +2 -2
  120. package/operations/find.d.ts.map +1 -1
  121. package/operations/find.js +1 -1
  122. package/operations/find.js.map +1 -1
  123. package/operations/findOne.d.ts +2 -2
  124. package/operations/findOne.d.ts.map +1 -1
  125. package/operations/findOne.js +1 -1
  126. package/operations/findOne.js.map +1 -1
  127. package/operations/insert.d.ts +3 -3
  128. package/operations/insert.d.ts.map +1 -1
  129. package/operations/insert.js +2 -2
  130. package/operations/insert.js.map +1 -1
  131. package/operations/sync.d.ts +1 -1
  132. package/operations/sync.d.ts.map +1 -1
  133. package/operations/sync.js +1 -1
  134. package/operations/sync.js.map +1 -1
  135. package/operations/tableExists.d.ts +1 -1
  136. package/operations/tableExists.d.ts.map +1 -1
  137. package/operations/update.d.ts +3 -3
  138. package/operations/update.d.ts.map +1 -1
  139. package/operations/update.js +2 -2
  140. package/operations/update.js.map +1 -1
  141. package/package.json +4 -12
  142. package/schema/index.d.ts +1 -1
  143. package/schema/index.d.ts.map +1 -1
  144. package/types.d.ts +4 -4
  145. package/types.d.ts.map +1 -1
  146. package/utils/queryParser.d.ts +1 -1
  147. package/utils/queryParser.d.ts.map +1 -1
  148. package/utils/queryParser.js +1 -1
  149. package/utils/queryParser.js.map +1 -1
  150. package/utils/typeChecker.d.ts +1 -1
  151. package/utils/typeChecker.d.ts.map +1 -1
  152. package/utils/typeChecker.js +1 -1
  153. package/utils/typeChecker.js.map +1 -1
@@ -0,0 +1,587 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ import util from "util"
19
+ import events from "events"
20
+
21
+ import Connection from "./connection.js"
22
+ import utils from "./utils.js"
23
+ import promiseUtils from "./promise-utils.js"
24
+ import errors from "./errors.js"
25
+ import clientOptions from "./client-options.js"
26
+
27
+ // Used to get the index of the connection with less in-flight requests
28
+ let connectionIndex = 0
29
+ const connectionIndexOverflow = Math.pow(2, 15)
30
+
31
+ let defaultOptions
32
+
33
+ /**
34
+ * Represents the possible states of the pool.
35
+ * Possible state transitions:
36
+ * - From initial to closing: The pool must be closed because the host is ignored.
37
+ * - From initial to shuttingDown: The pool is being shutdown as a result of a client shutdown.
38
+ * - From closing to initial state: The pool finished closing connections (is now ignored) and it resets to
39
+ * initial state in case the host is marked as local/remote in the future.
40
+ * - From closing to shuttingDown (rare): It was marked as ignored, now the client is being shutdown.
41
+ * - From shuttingDown to shutdown: Finished shutting down, the pool should not be reused.
42
+ * @private
43
+ */
44
+ const state = {
45
+ // Initial state: open / opening / ready to be opened
46
+ initial: 0,
47
+ // When the pool is being closed as part of a distance change
48
+ closing: 1,
49
+ // When the pool is being shutdown for good
50
+ shuttingDown: 2,
51
+ // When the pool has being shutdown
52
+ shutDown: 4,
53
+ }
54
+
55
+ /**
56
+ * Represents a pool of connections to a host
57
+ */
58
+ class HostConnectionPool extends events.EventEmitter {
59
+ /**
60
+ * Creates a new instance of HostConnectionPool.
61
+ * @param {Host} host
62
+ * @param {Number} protocolVersion Initial protocol version
63
+ * @extends EventEmitter
64
+ */
65
+ constructor(host, protocolVersion) {
66
+ super()
67
+ this._address = host.address
68
+ this._newConnectionTimeout = null
69
+ this._state = state.initial
70
+ this._opening = false
71
+ this._host = host
72
+ this.responseCounter = 0
73
+ this.options = host.options
74
+ this.protocolVersion = protocolVersion
75
+ this.coreConnectionsLength = 1
76
+ /**
77
+ * An immutable array of connections
78
+ * @type {Array.<Connection>}
79
+ */
80
+ this.connections = utils.emptyArray
81
+ this.setMaxListeners(0)
82
+ this.log = utils.log
83
+ }
84
+
85
+ getInFlight() {
86
+ const length = this.connections.length
87
+ if (length === 1) {
88
+ return this.connections[0].getInFlight()
89
+ }
90
+
91
+ let sum = 0
92
+ for (let i = 0; i < length; i++) {
93
+ sum += this.connections[i].getInFlight()
94
+ }
95
+ return sum
96
+ }
97
+
98
+ /**
99
+ * Gets the least busy connection from the pool.
100
+ * @param {Connection} [previousConnection] When provided, the pool should attempt to obtain a different connection.
101
+ * @returns {Connection!}
102
+ * @throws {Error}
103
+ * @throws {BusyConnectionError}
104
+ */
105
+ borrowConnection(previousConnection) {
106
+ if (this.connections.length === 0) {
107
+ throw new Error("No connection available")
108
+ }
109
+
110
+ const maxRequests = this.options.pooling.maxRequestsPerConnection
111
+ const c = HostConnectionPool.minInFlight(
112
+ this.connections,
113
+ maxRequests,
114
+ previousConnection,
115
+ )
116
+
117
+ if (c.getInFlight() >= maxRequests) {
118
+ throw new errors.BusyConnectionError(
119
+ this._address,
120
+ maxRequests,
121
+ this.connections.length,
122
+ )
123
+ }
124
+
125
+ return c
126
+ }
127
+
128
+ /**
129
+ * Gets the connection with the minimum number of in-flight requests.
130
+ * Only checks for 2 connections (round-robin) and gets the one with minimum in-flight requests, as long as
131
+ * the amount of in-flight requests is lower than maxRequests.
132
+ * @param {Array.<Connection>} connections
133
+ * @param {Number} maxRequests
134
+ * @param {Connection} previousConnection When provided, it will attempt to obtain a different connection.
135
+ * @returns {Connection!}
136
+ */
137
+ static minInFlight(connections, maxRequests, previousConnection) {
138
+ const length = connections.length
139
+ if (length === 1) {
140
+ return connections[0]
141
+ }
142
+
143
+ // Use a single index for all hosts as a simplified way to balance the load between connections
144
+ connectionIndex++
145
+ if (connectionIndex >= connectionIndexOverflow) {
146
+ connectionIndex = 0
147
+ }
148
+
149
+ let current
150
+ for (
151
+ let index = connectionIndex;
152
+ index < connectionIndex + length;
153
+ index++
154
+ ) {
155
+ current = connections[index % length]
156
+ if (current === previousConnection) {
157
+ // Increment the index and skip
158
+ current = connections[++index % length]
159
+ }
160
+
161
+ let next = connections[(index + 1) % length]
162
+ if (next === previousConnection) {
163
+ // Skip
164
+ next = connections[(index + 2) % length]
165
+ }
166
+
167
+ if (next.getInFlight() < current.getInFlight()) {
168
+ current = next
169
+ }
170
+
171
+ if (current.getInFlight() < maxRequests) {
172
+ // Check as few connections as possible, as long as the amount of in-flight
173
+ // requests is lower than maxRequests
174
+ break
175
+ }
176
+ }
177
+ return current
178
+ }
179
+
180
+ /**
181
+ * Creates all the connections in the pool and switches the keyspace of each connection if needed.
182
+ * @param {string} keyspace
183
+ */
184
+ async warmup(keyspace) {
185
+ if (this.connections.length < this.coreConnectionsLength) {
186
+ while (this.connections.length < this.coreConnectionsLength) {
187
+ await this._attemptNewConnection()
188
+ }
189
+
190
+ this.log(
191
+ "info",
192
+ `Connection pool to host ${this._address} created with ${this.connections.length} connection(s)`,
193
+ )
194
+ } else {
195
+ this.log(
196
+ "info",
197
+ `Connection pool to host ${this._address} contains ${this.connections.length} connection(s)`,
198
+ )
199
+ }
200
+
201
+ if (keyspace) {
202
+ try {
203
+ for (const connection of this.connections) {
204
+ await connection.changeKeyspace(keyspace)
205
+ }
206
+ } catch (err) {
207
+ // Log it and move on, it could be a momentary schema mismatch failure
208
+ this.log(
209
+ "warning",
210
+ `Connection(s) to host ${this._address} could not be switched to keyspace ${keyspace}`,
211
+ )
212
+ }
213
+ }
214
+ }
215
+
216
+ /** @returns {Connection} */
217
+ _createConnection() {
218
+ const endpointOrServerName = !this.options.sni
219
+ ? this._address
220
+ : this._host.hostId.toString()
221
+
222
+ const c = new Connection(
223
+ endpointOrServerName,
224
+ this.protocolVersion,
225
+ this.options,
226
+ )
227
+ this._addListeners(c)
228
+ return c
229
+ }
230
+
231
+ /** @param {Connection} c */
232
+ _addListeners(c) {
233
+ c.on("responseDequeued", () => this.responseCounter++)
234
+
235
+ const self = this
236
+ function connectionErrorCallback() {
237
+ // The socket is not fully open / can not send heartbeat
238
+ self.remove(c)
239
+ }
240
+ c.on("idleRequestError", connectionErrorCallback)
241
+ c.on("socketClose", connectionErrorCallback)
242
+ }
243
+
244
+ addExistingConnection(c) {
245
+ this._addListeners(c)
246
+ // Use a copy of the connections array
247
+ this.connections = this.connections.slice(0)
248
+ this.connections.push(c)
249
+ }
250
+
251
+ /**
252
+ * Prevents reconnection timeout from triggering
253
+ */
254
+ clearNewConnectionAttempt() {
255
+ if (!this._newConnectionTimeout) {
256
+ return
257
+ }
258
+ clearTimeout(this._newConnectionTimeout)
259
+ this._newConnectionTimeout = null
260
+ }
261
+
262
+ /**
263
+ * Tries to open a new connection.
264
+ * If a connection is being opened, it will resolve when the existing open task completes.
265
+ * @returns {Promise<void>}
266
+ */
267
+ async _attemptNewConnection() {
268
+ if (this._opening) {
269
+ // Wait for the event to fire
270
+ return await promiseUtils.fromEvent(this, "open")
271
+ }
272
+
273
+ this._opening = true
274
+
275
+ const c = this._createConnection()
276
+ let err
277
+
278
+ try {
279
+ await c.openAsync()
280
+ } catch (e) {
281
+ err = e
282
+ this.log(
283
+ "warning",
284
+ `Connection to ${this._address} could not be created: ${err}`,
285
+ err,
286
+ )
287
+ }
288
+
289
+ if (this.isClosing()) {
290
+ this.log(
291
+ "info",
292
+ `Connection to ${this._address} opened successfully but pool was being closed`,
293
+ )
294
+ err = new Error("Connection closed")
295
+ }
296
+
297
+ if (!err) {
298
+ // Append the connection to the pool.
299
+ // Use a copy of the connections array.
300
+ const newConnections = this.connections.slice(0)
301
+ newConnections.push(c)
302
+ this.connections = newConnections
303
+ this.log(
304
+ "info",
305
+ `Connection to ${this._address} opened successfully`,
306
+ )
307
+ } else {
308
+ promiseUtils.toBackground(c.closeAsync())
309
+ }
310
+
311
+ // Notify that creation finished by setting the flag and emitting the event
312
+ this._opening = false
313
+ this.emit("open", err, c)
314
+
315
+ if (err) {
316
+ // Opening failed
317
+ throw err
318
+ }
319
+ }
320
+
321
+ attemptNewConnectionImmediate() {
322
+ const self = this
323
+ function openConnection() {
324
+ self.clearNewConnectionAttempt()
325
+ self.scheduleNewConnectionAttempt(0)
326
+ }
327
+
328
+ if (this._state === state.initial) {
329
+ return openConnection()
330
+ }
331
+
332
+ if (this._state === state.closing) {
333
+ return this.once("close", openConnection)
334
+ }
335
+ // In the case the pool its being / has been shutdown for good
336
+ // Do not attempt to create a new connection.
337
+ }
338
+
339
+ /**
340
+ * Closes the connection and removes a connection from the pool.
341
+ * @param {Connection} connection
342
+ */
343
+ remove(connection) {
344
+ // locating an object by position in the array is O(n), but normally there should be between 1 to 8 connections.
345
+ const index = this.connections.indexOf(connection)
346
+ if (index < 0) {
347
+ // it was already removed from the connections and it's closing
348
+ return
349
+ }
350
+ // remove the connection from the pool, using an pool copy
351
+ const newConnections = this.connections.slice(0)
352
+ newConnections.splice(index, 1)
353
+ this.connections = newConnections
354
+ // close the connection
355
+ setImmediate(function removeClose() {
356
+ connection.close()
357
+ })
358
+ this.emit("remove")
359
+ }
360
+
361
+ /**
362
+ * @param {Number} delay
363
+ */
364
+ scheduleNewConnectionAttempt(delay) {
365
+ if (this.isClosing()) {
366
+ return
367
+ }
368
+
369
+ const self = this
370
+
371
+ this._newConnectionTimeout = setTimeout(
372
+ function newConnectionTimeoutExpired() {
373
+ self._newConnectionTimeout = null
374
+ if (self.connections.length >= self.coreConnectionsLength) {
375
+ // new connection can be scheduled while a new connection is being opened
376
+ // the pool has the appropriate size
377
+ return
378
+ }
379
+
380
+ if (delay > 0 && self.options.sni) {
381
+ // We use delay > 0 as an indication that it's a reconnection.
382
+ // A reconnection schedule can use delay = 0 as well, but it's a good enough signal.
383
+ promiseUtils.toBackground(
384
+ self.options.sni.addressResolver
385
+ .refresh()
386
+ .then(() => self._attemptNewConnection()),
387
+ )
388
+ return
389
+ }
390
+
391
+ promiseUtils.toBackground(self._attemptNewConnection())
392
+ },
393
+ delay,
394
+ )
395
+ }
396
+
397
+ hasScheduledNewConnection() {
398
+ return !!this._newConnectionTimeout || this._opening
399
+ }
400
+
401
+ /**
402
+ * Increases the size of the connection pool in the background, if needed.
403
+ */
404
+ increaseSize() {
405
+ if (
406
+ this.connections.length < this.coreConnectionsLength &&
407
+ !this.hasScheduledNewConnection()
408
+ ) {
409
+ // schedule the next connection in the background
410
+ this.scheduleNewConnectionAttempt(0)
411
+ }
412
+ }
413
+
414
+ /**
415
+ * Gets the amount of responses and resets the internal counter.
416
+ * @returns {number}
417
+ */
418
+ getAndResetResponseCounter() {
419
+ const temp = this.responseCounter
420
+ this.responseCounter = 0
421
+ return temp
422
+ }
423
+
424
+ /**
425
+ * Gets a boolean indicating if the pool is being closed / shutting down or has been shutdown.
426
+ */
427
+ isClosing() {
428
+ return this._state !== state.initial
429
+ }
430
+
431
+ /**
432
+ * Gracefully waits for all in-flight requests to finish and closes the pool.
433
+ */
434
+ drainAndShutdown() {
435
+ if (this.isClosing()) {
436
+ // Its already closing / shutting down
437
+ return
438
+ }
439
+
440
+ this._state = state.closing
441
+ this.clearNewConnectionAttempt()
442
+
443
+ if (this.connections.length === 0) {
444
+ return this._afterClosing()
445
+ }
446
+
447
+ const self = this
448
+ const connections = this.connections
449
+ this.connections = utils.emptyArray
450
+ let closedConnections = 0
451
+ this.log(
452
+ "info",
453
+ util.format(
454
+ "Draining and closing %d connections to %s",
455
+ connections.length,
456
+ this._address,
457
+ ),
458
+ )
459
+ let wasClosed = false
460
+ // eslint-disable-next-line prefer-const
461
+ let checkShutdownTimeout
462
+
463
+ for (let i = 0; i < connections.length; i++) {
464
+ const c = connections[i]
465
+ if (c.getInFlight() === 0) {
466
+ getDelayedClose(c)()
467
+ continue
468
+ }
469
+ c.emitDrain = true
470
+ c.once("drain", getDelayedClose(c))
471
+ }
472
+
473
+ function getDelayedClose(connection) {
474
+ return function delayedClose() {
475
+ connection.close()
476
+ if (++closedConnections < connections.length) {
477
+ return
478
+ }
479
+ if (wasClosed) {
480
+ return
481
+ }
482
+ wasClosed = true
483
+ if (checkShutdownTimeout) {
484
+ clearTimeout(checkShutdownTimeout)
485
+ }
486
+ self._afterClosing()
487
+ }
488
+ }
489
+
490
+ // Check that after sometime (readTimeout + 100ms) the connections have been drained
491
+ const delay =
492
+ (this.options.socketOptions.readTimeout ||
493
+ getDefaultOptions().socketOptions.readTimeout) + 100
494
+ checkShutdownTimeout = setTimeout(function checkShutdown() {
495
+ wasClosed = true
496
+ connections.forEach(function connectionEach(c) {
497
+ c.close()
498
+ })
499
+ self._afterClosing()
500
+ }, delay)
501
+ }
502
+
503
+ _afterClosing() {
504
+ const self = this
505
+
506
+ function resetState() {
507
+ if (self._state === state.shuttingDown) {
508
+ self._state = state.shutDown
509
+ } else {
510
+ self._state = state.initial
511
+ }
512
+
513
+ self.emit("close")
514
+
515
+ if (self._state === state.shutDown) {
516
+ self.emit("shutdown")
517
+ }
518
+ }
519
+
520
+ if (this._opening) {
521
+ // The pool is growing, reset the state back to init once the open finished (without any new connection)
522
+ return this.once("open", resetState)
523
+ }
524
+
525
+ resetState()
526
+ }
527
+
528
+ /**
529
+ * @returns {Promise<void>}
530
+ */
531
+ async shutdown() {
532
+ this.clearNewConnectionAttempt()
533
+
534
+ if (!this.connections.length) {
535
+ this._state = state.shutDown
536
+ return
537
+ }
538
+
539
+ const previousState = this._state
540
+ this._state = state.shuttingDown
541
+
542
+ if (
543
+ previousState === state.closing ||
544
+ previousState === state.shuttingDown
545
+ ) {
546
+ // When previous state was closing, it will drain all connections and close them
547
+ // When previous state was "shuttingDown", it will close all the connections
548
+ // Once it's completed, shutdown event will be emitted
549
+ return promiseUtils.fromEvent(this, "shutdown")
550
+ }
551
+
552
+ await this._closeAllConnections()
553
+
554
+ this._state = state.shutDown
555
+ this.emit("shutdown")
556
+ }
557
+
558
+ async _closeAllConnections() {
559
+ const connections = this.connections
560
+ // point to an empty array
561
+ this.connections = utils.emptyArray
562
+ if (connections.length === 0) {
563
+ return
564
+ }
565
+
566
+ this.log(
567
+ "info",
568
+ util.format(
569
+ "Closing %d connections to %s",
570
+ connections.length,
571
+ this._address,
572
+ ),
573
+ )
574
+
575
+ await Promise.all(connections.map((c) => c.closeAsync()))
576
+ }
577
+ }
578
+
579
+ /** Lazily loads the default options */
580
+ function getDefaultOptions() {
581
+ if (defaultOptions === undefined) {
582
+ defaultOptions = clientOptions.defaultOptions()
583
+ }
584
+ return defaultOptions
585
+ }
586
+
587
+ export default HostConnectionPool