1=================================
2Connection Monitoring and Pooling
3=================================
4
5:Title: Connection Monitoring and Pooling
6:Author: Dan Aprahamian
7:Advisory Group: Jeff Yemin, Matt Broadstone
8:Approvers: Bernie Hackett, Dan Pasette, Jeff Yemin, Matt Broadstone, Sam Rossi, Scott L'Hommedieu
9:Status: Accepted
10:Type: Standards
11:Minimum Server Version: N/A
12:Last Modified: June 11, 2019
13:Version: 1.1.0
14
15.. contents::
16
17Abstract
18========
19
20Drivers currently support a variety of options that allow users to configure connection pooling behavior. Users are confused by drivers supporting different subsets of these options. Additionally, drivers implement their connection pools differently, making it difficult to design cross-driver pool functionality. By unifying and codifying pooling options and behavior across all drivers, we will increase user comprehension and code base maintainability.
21
22META
23====
24
25The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in `RFC 2119 <https://www.ietf.org/rfc/rfc2119.txt>`_.
26
27Definitions
28===========
29
30Endpoint
31~~~~~~~~
32
33For convenience, an Endpoint refers to either a **mongod** or **mongos** instance.
34
35Thread
36~~~~~~
37
38For convenience, a Thread refers to:
39
40- A shared-address-space process (a.k.a. a thread) in multi-threaded drivers
41- An Execution Frame / Continuation in asynchronous drivers
42- A goroutine in Go
43
44Behavioral Description
45======================
46
47Which Drivers this applies to
48~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49
50This specification is solely concerned with drivers that implement a connection pool. A driver SHOULD implement a connection pool, but is not required to.
51
52Connection Pool Options
53~~~~~~~~~~~~~~~~~~~~~~~
54
55All drivers that implement a connection pool MUST implement and conform to the same MongoClient options. There can be slight deviation in naming to make the options idiomatic to the driver language.
56
57Connection Pool Behaviors
58~~~~~~~~~~~~~~~~~~~~~~~~~
59
60All driver connection pools MUST provide an API that allows the driver to check out a connection, check in a connection back to the pool, and clear all connections in the pool. This API is for internal use only, and SHOULD NOT be documented as a public API.
61
62Connection Pool Monitoring
63~~~~~~~~~~~~~~~~~~~~~~~~~~
64
65All drivers that implement a connection pool MUST provide an API that allows users to subscribe to events emitted from the pool.
66
67Detailed Design
68===============
69
70.. _connection-pool-options-1:
71
72Connection Pool Options
73~~~~~~~~~~~~~~~~~~~~~~~
74
75Drivers that implement a Connection Pool MUST support the following ConnectionPoolOptions:
76
77.. code:: typescript
78
79 interface ConnectionPoolOptions {
80 /**
81 * The maximum number of connections that may be associated
82 * with a pool at a given time. This includes in use and
83 * available connections.
84 * If specified, MUST be an integer >= 0.
85 * A value of 0 means there is no limit.
86 * Defaults to 100.
87 */
88 maxPoolSize?: number;
89
90 /**
91 * The minimum number of connections that MUST exist at any moment
92 * in a single connection pool.
93 * If specified, MUST be an integer >= 0. If maxPoolSize is > 0
94 * then minPoolSize must be <= maxPoolSize
95 * Defaults to 0.
96 */
97 minPoolSize?: number;
98
99 /**
100 * The maximum amount of time a connection should remain idle
101 * in the connection pool before being marked idle.
102 * If specified, MUST be a number >= 0.
103 * A value of 0 means there is no limit.
104 * Defaults to 0.
105 */
106 maxIdleTimeMS?: number;
107 }
108
109Additionally, Drivers that implement a Connection Pool MUST support the following ConnectionPoolOptions UNLESS that driver meets ALL of the following conditions:
110
111- The driver/language currently has an idiomatic timeout mechanism implemented
112- The timeout mechanism conforms to `the aggressive requirement of timing out a thread in the WaitQueue <#w1dcrm950sbn>`__
113
114.. code:: typescript
115
116 interface ConnectionPoolOptions {
117 /**
118 * The maximum amount of time a thread can wait for a connection
119 * to become available.
120 * If specified, MUST be a number >= 0.
121 * A value of 0 means there is no limit.
122 * Defaults to 0.
123 */
124 waitQueueTimeoutMS?: number;
125 }
126
127These options MUST be specified at the MongoClient level, and SHOULD be named in a manner idiomatic to the driver's language. All connection pools created by a MongoClient MUST use the same ConnectionPoolOptions.
128
129When parsing a mongodb connection string, a user MUST be able to specify these options using the default names specified above.
130
131Deprecated Options
132------------------
133
134The following ConnectionPoolOptions are considered deprecated. They MUST NOT be implemented if they do not already exist in a driver, and they SHOULD be deprecated and removed from drivers that implement them as early as possible:
135
136.. code:: typescript
137
138 interface ConnectionPoolOptions {
139 /**
140 * The maximum number of threads that can simultaneously wait
141 * for a connection to become available.
142 */
143 waitQueueSize?: number;
144
145 /**
146 * An alternative way of setting waitQueueSize, it specifies
147 * the maximum number of threads that can wait per connection.
148 * waitQueueSize === waitQueueMultiple \* maxPoolSize
149 */
150 waitQueueMultiple?: number
151 }
152
153Connection Pool Members
154~~~~~~~~~~~~~~~~~~~~~~~
155
156Connection
157----------
158
159A driver-defined wrapper around a single TCP/IP connection to an Endpoint. A Connection has the following properties:
160
161- **Single Endpoint:** A Connection MUST be associated with a single Endpoint. A Connection MUST NOT be associated with multiple Endpoints.
162- **Single Lifetime:** A Connection MUST NOT be used after it is closed.
163- **Single Owner:** A Connection MUST belong to exactly one Pool, and MUST NOT be shared across multiple pools
164- **Single Track:** A Connection MUST limit itself to one request / response at a time. A Connection MUST NOT multiplex/pipeline requests to an Endpoint.
165- **Monotonically Increasing ID:** A Connection MUST have an ID number associated with it. Connection IDs within a Pool MUST be assigned in order of creation, starting at 1 and increasing by 1 for each new Connection.
166- **Valid Connection:** A connection MUST NOT be checked out of the pool until it has successfully and fully completed a MongoDB Handshake and Authentication as specified in the `Handshake <https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst>`__, `OP_COMPRESSED <https://github.com/mongodb/specifications/blob/master/source/compression/OP_COMPRESSED.rst>`__, and `Authentication <https://github.com/mongodb/specifications/blob/master/source/auth/auth.rst>`__ specifications.
167- **Perishable**: it is possible for a connection to become **Perished**. A connection is considered perished if any of the following are true:
168
169 - **Stale:** The connection's generation does not match the generation of the parent pool
170 - **Idle:** The connection is currently available and readyToUse, and has been for longer than **maxIdleTimeMS**.
171 - **Errored:** The connection has experienced an error that indicates the connection is no longer recommended for use. Examples include, but are not limited to:
172
173 - Network Error
174 - Network Timeout
175 - Endpoint closing the connection
176 - Driver-Side Timeout
177 - Wire-Protocol Error
178
179.. code:: typescript
180
181 interface Connection {
182 /**
183 * An id number associated with the connection
184 */
185 id: number;
186
187 /**
188 * The address of the pool that owns this connection
189 */
190 address: string;
191
192 /**
193 * An integer representing the “generation” of the pool
194 * when this connection was created
195 */
196 generation: number;
197 }
198
199WaitQueue
200---------
201
202A concept that represents pending requests for connections. When a thread requests a Connection from a Pool, the thread enters the Pool's WaitQueue. A thread stays in the WaitQueue until it either receives a Connection or times out. A WaitQueue has the following traits:
203
204- **Thread-Safe**: When multiple threads attempt to enter or exit a WaitQueue, they do so in a thread-safe manner.
205- **Ordered/Fair**: When connections are made available, they are issued out to threads in the order that the threads entered the WaitQueue.
206- **Timeout aggressively:** If **waitQueueTimeoutMS** is set, members of a WaitQueue MUST timeout if they are enqueued for longer than waitQueueTimeoutMS. Members of a WaitQueue MUST timeout aggressively, and MUST leave the WaitQueue immediately upon timeout.
207
208The implementation details of a WaitQueue are left to the driver.
209Example implementations include:
210
211- A fair Semaphore
212- A Queue of callbacks
213
214Connection Pool
215---------------
216
217A driver-defined entity that encapsulates all non-monitoring connections associated with a single Endpoint. The pool has the following properties:
218
219- **Thread Safe:** All Pool behaviors MUST be thread safe.
220- **Not Fork-Safe:** A Pool is explicitly not fork-safe. If a Pool detects that is it being used by a forked process, it MUST immediately clear itself and update it's pid
221- **Single Owner:** A Pool MUST be associated with exactly one Endpoint, and MUST NOT be shared between Endpoints.
222- **Emit Events:** A Pool MUST emit pool events when dictated by this spec (see `Connection Pool Monitoring <https://docs.google.com/document/d/1AT1vCSBXB-0MQUqkusIukMngSvlyNU93qe9tBxbcfiY/edit?disco=AAAACWk9Jo4&ts=5bec82a4#heading=h.75j6jnmktzyn>`__). Users MUST be able to subscribe to emitted events in a manner idiomatic to their language and driver.
223- **Closeable:** A Pool MUST be able to be manually closed. When a Pool is closed, the following behaviors change:
224
225 - Checking in a Connection to the Pool automatically closes the connection
226 - Attempting to check out a Connection from the Pool results in an Error
227
228- **Capped:** a pool is capped if **maxPoolSize** is set to a non-zero value. If a pool is capped, then it's total number of connections (including available and in use) MUST NOT exceed **maxPoolSize**
229
230.. code:: typescript
231
232 interface ConnectionPool {
233 /**
234 * The Queue of threads waiting for a connection to be available
235 */
236 waitQueue: WaitQueue;
237
238 /**
239 * A generation number representing the SDAM generation of the pool
240 */
241 generation: number;
242
243 /**
244 * An integer expressing how many total connections
245 * (active + in use) the pool currently has
246 */
247 totalConnectionCount: number;
248
249 /**
250 * An integer expressing how many connections are currently
251 * available in the pool.
252 */
253 availableConnectionCount: number;
254
255 /**
256 * Returns a connection for use
257 */
258 checkOut(): Connection;
259
260 /**
261 * Check in a connection back to the connection pool
262 */
263 checkIn(connection: Connection): void;
264
265 /**
266 * Mark all current connections as stale.
267 */
268 clear(): void;
269
270 /**
271 * Closes the pool, preventing the pool from creating and returning new Connections
272 */
273 close(): void;
274 }
275
276.. _connection-pool-behaviors-1:
277
278Connection Pool Behaviors
279~~~~~~~~~~~~~~~~~~~~~~~~~
280
281Creating a Connection Pool
282--------------------------
283
284Pool creation is mostly an implementation detail specific to the driver language. If minPoolSize is set, the pool MUST immediately create enough connections such that totalConnections >= minPoolSize. These connections MUST be created in a non-blocking manner. Drivers SHOULD additionally connect these connections if it is possible to do so in a non-blocking manner, either via the use of a Background Thread or via asynchronous I/O.
285
286.. code::
287
288 set generation to 0
289 emit PoolCreatedEvent
290 if minPoolSize is set:
291 while totalConnectionCount < minPoolSize:
292 create connection
293 # If this can be done without blocking, ensure that connection
294 # is ready to use
295
296
297Closing a Connection Pool
298-------------------------
299
300When a pool is closed, it MUST first close all available connections in that pool. This results in the following behavior changes:
301
302- In use connections MUST be closed when they are checked in to the closed pool.
303- Attempting to check out a connection MUST result in an error.
304
305.. code::
306
307 mark pool as CLOSED
308 for connection in availableConnections:
309 close connection
310 emit PoolClosedEvent
311
312Creating a Connection (Internal Implementation)
313-----------------------------------------------
314
315When creating a connection, the initial Connection is in a “set up” state. This only creates a “virtual” connection, and performs no I/O. The Connection MUST NOT be made available until it has completed its connection as described `here <#connecting-a-connection-internal-implementation>`__.
316
317.. code::
318
319 connection = new Connection()
320 mark connection as available
321 emit ConnectionCreatedEvent
322 return connection
323
324Connecting a Connection (Internal Implementation)
325-------------------------------------------------
326
327Before a connection can be returned outside of the pool, it must be “set up”. This process involves performing the initial handshake, handling OP_COMPRESSED, and performing authentication.
328
329.. code::
330
331 try:
332 connect connection via TCP / TLS
333 perform connection handshake
334 handle OP_COMPRESSED
335 perform connection authentication
336 mark connection as readyToUse
337 emit ConnectionReadyEvent
338 return connection
339 except error:
340 close connection
341 throw error # Propagate error in manner idiomatic to language.
342
343
344Closing a Connection (Internal Implementation)
345----------------------------------------------
346
347When a Connection is closed, it MUST first be marked as closed, removing it from being counted as available, in use, or setup. Once the connection is marked as closed, the Connection can perform whatever teardown is necessary. The Driver SHOULD perform the teardown in a non-blocking manner.
348
349.. code::
350
351 mark connection as closed
352 emit ConnectionClosedEvent
353
354 # The following can happen at a later time
355 connection.close()
356
357Checking Out a Connection
358-------------------------
359
360A Pool MUST have a method of allowing the driver to check out a Connection. Checking out a Connection involves entering the WaitQueue, and waiting for a Connection to become available. If the thread times out in the WaitQueue, an error is thrown.
361
362If, in the process of iterating available connections in the pool by the checkOut method, a perished connection is encountered, such a connection MUST be closed and the iteration of available connections MUST continue until either a non-perished available connection is found or the list of available connections is exhausted. If no connections are available and the total number of connections is less than maxPoolSize, the pool MUST create and return a new Connection.
363
364If the pool is closed, any attempt to check out a connection MUST throw an Error, and any items in the waitQueue MUST be removed from the waitQueue and throw an Error.
365
366If minPoolSize is set, the Connection Pool must have at least minPoolSize total connections. If the pool does not implement a background thread as specified here, the checkOut method is responsible for ensuring this requirement.
367
368A Connection MUST NOT be checked out until it is readyToUse. In addition, the Pool MUST NOT block other threads from checking out connections while waiting for a connection to be readyToUse.
369
370
371.. code::
372
373 connection = Null
374 emit ConnectionCheckOutStartedEvent
375 try:
376 enter WaitQueue
377 wait until at top of wait queue
378 # Note that in a lock-based implementation of the wait queue would
379 # only allow one thread in the following block at a time
380 while connection is Null:
381 if a connection is available:
382 while connection is Null and a connection is available:
383 connection = next available connection
384 if connection is perished:
385 close connection
386 connection = Null
387 else if totalConnectionCount < maxPoolSize:
388 connection = create connection
389 # If there is no background thread, the pool MUST ensure that
390 # at least minPoolSize connections are in the pool.
391 # This SHOULD be done in a non-blocking manner
392 while totalConnectionCount < minPoolSize:
393 create connection
394 except pool is closed:
395 emit ConnectionCheckOutFailedEvent(reason="poolClosed")
396 throw PoolClosedError
397 except timeout:
398 emit ConnectionCheckOutFailedEvent(reason="timeout")
399 throw WaitQueueTimeoutError
400 finally:
401 # This must be done in all drivers
402 leave wait queue
403
404 # If the connection has not been connected yet, the connection
405 # (TCP, TLS, handshake, compression, and auth) must be performed
406 # before the connection is returned. This MUST NOT block other threads
407 # from acquiring connections.
408 if connection is not readyToUse:
409 try:
410 set up connection
411 except set up connection error:
412 emit ConnectionCheckOutFailedEvent(reason="error")
413 throw
414
415 mark connection as in use
416 emit ConnectionCheckedOutEvent
417 return connection
418
419Checking In a Connection
420------------------------
421
422A Pool MUST have a method of allowing the driver to check in a Connection. The driver MUST NOT be allowed to check in a Connection to a Pool that did not create that Connection, and MUST throw an Error if this is attempted.
423
424When the Connection is checked in, it is closed if any of the following are true:
425
426- The connection is perished.
427- The pool has been closed.
428
429Otherwise, the connection is marked as available.
430
431.. code::
432
433 emit ConnectionCheckedInEvent
434 if connection is perished OR pool is closed:
435 close connection
436 else:
437 mark connection as available
438
439Clearing a Connection Pool
440--------------------------
441
442A Pool MUST have a method of clearing all Connections when instructed. Rather than iterating through every Connection, this method should simply increment the generation of the Pool, implicitly marking all current connections as stale. The checkOut and checkIn algorithms will handle clearing out stale connections. If a user is subscribed to Connection Monitoring events, a PoolClearedEvent MUST be emitted after incrementing the generation.
443
444Forking
445-------
446
447A Connection is explicitly not fork-safe. The proper behavior in the case of a fork is to ResetAfterFork by:
448
449- clear all Connection Pools in the child process
450- closing all Connections in the child-process.
451
452Drivers that support forking MUST document that connections to an Endpoint are not fork-safe, and document the proper way to ResetAfterFork in the driver.
453
454Drivers MAY aggressively ResetAfterFork if the driver detects it has been forked.
455
456Optional Behaviors
457------------------
458
459The following features of a Connection Pool SHOULD be implemented if they make sense in the driver and driver's language.
460
461Background Thread
462^^^^^^^^^^^^^^^^^
463
464A Pool SHOULD have a background Thread that is responsible for
465monitoring the state of all available connections. This background
466thread SHOULD
467
468- Create and connect connections to ensure that the pool always satisfies **minPoolSize**
469- Remove and close perished available connections.
470
471withConnection
472^^^^^^^^^^^^^^
473
474A Pool SHOULD implement a scoped resource management mechanism idiomatic to their language to prevent Connections from not being checked in. Examples include `Python's "with" statement <https://docs.python.org/3/whatsnew/2.6.html#pep-343-the-with-statement>`__ and `C#'s "using" statement <https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement>`__. If implemented, drivers SHOULD use this method as the default method of checking out and checking in Connections.
475
476.. _connection-pool-monitoring-1:
477
478Connection Pool Monitoring
479~~~~~~~~~~~~~~~~~~~~~~~~~~
480
481All drivers that implement a connection pool MUST provide an API that allows users to subscribe to events emitted from the pool. If a user subscribes to Connection Monitoring events, these events MUST be emitted when specified in “Connection Pool Behaviors”. Events SHOULD be created and subscribed to in a manner idiomatic to their language and driver.
482
483Events
484------
485
486
487.. code:: typescript
488
489 /**
490 * Emitted when a Connection Pool is created
491 */
492 interface PoolCreatedEvent {
493 /**
494 * The ServerAddress of the Endpoint the pool is attempting to connect to.
495 */
496 address: string;
497
498 /**
499 * Any non-default pool options that were set on this Connection Pool.
500 */
501 options: {...}
502 }
503
504 /**
505 * Emitted when a Connection Pool is cleared
506 */
507 interface PoolClearedEvent {
508 /**
509 * The ServerAddress of the Endpoint the pool is attempting to connect to.
510 */
511 address: string;
512 }
513
514 /**
515 * Emitted when a Connection Pool is closed
516 */
517 interface PoolClosedEvent {
518 /**
519 * The ServerAddress of the Endpoint the pool is attempting to connect to.
520 */
521 address: string;
522 }
523
524 /**
525 * Emitted when a Connection Pool creates a Connection object.
526 * NOTE: This does not mean that the connection is ready for use.
527 */
528 interface ConnectionCreatedEvent {
529 /**
530 * The ServerAddress of the Endpoint the pool is attempting to connect to.
531 */
532 address: string;
533
534 /**
535 * The ID of the Connection
536 */
537 connectionId: number;
538 }
539
540 /**
541 * Emitted when a Connection has finished its setup, and is now ready to use
542 */
543 interface ConnectionReadyEvent {
544 /**
545 * The ServerAddress of the Endpoint the pool is attempting to connect to.
546 */
547 address: string;
548
549 /**
550 * The ID of the Connection
551 */
552 connectionId: number;
553 }
554
555 /**
556 * Emitted when a Connection Pool closes a Connection
557 */
558 interface ConnectionClosedEvent {
559 /**
560 * The ServerAddress of the Endpoint the pool is attempting to connect to.
561 */
562 address: string;
563
564 /**
565 * The ID of the Connection
566 */
567 connectionId: number;
568
569 /**
570 * A reason explaining why this connection was closed.
571 * Can be implemented as a string or enum.
572 * Current valid values are:
573 * - "stale": The pool was cleared, making the connection no longer valid
574 * - "idle": The connection became stale by being available for too long
575 * - "error": The connection experienced an error, making it no longer valid
576 * - "poolClosed": The pool was closed, making the connection no longer valid
577 */
578 reason: string|Enum;
579 }
580
581 /**
582 * Emitted when the driver starts attempting to check out a connection
583 */
584 interface ConnectionCheckOutStartedEvent {
585 /**
586 * The ServerAddress of the Endpoint the pool is attempting
587 * to connect to.
588 */
589 address: string;
590 }
591
592 /**
593 * Emitted when the driver's attempt to check out a connection fails
594 */
595 interface ConnectionCheckOutFailedEvent {
596 /**
597 * The ServerAddress of the Endpoint the pool is attempting to connect to.
598 */
599 address: string;
600
601 /**
602 * A reason explaining why connection check out failed.
603 * Can be implemented as a string or enum.
604 * Current valid values are:
605 * - "poolClosed": The pool was previously closed, and cannot provide new connections
606 * - "timeout": The connection check out attempt exceeded the specified timeout
607 * - "connectionError": The connection check out attempt experienced an error while setting up a new connection
608 */
609 reason: string|Enum;
610 }
611
612 /**
613 * Emitted when the driver successfully checks out a Connection
614 */
615 interface ConnectionCheckedOutEvent {
616 /**
617 * The ServerAddress of the Endpoint the pool is attempting to connect to.
618 */
619 address: string;
620
621 /**
622 * The ID of the Connection
623 */
624 connectionId: number;
625 }
626
627 /**
628 * Emitted when the driver checks in a Connection back to the Connection Pool
629 */
630 interface ConnectionCheckedInEvent {
631 /**
632 * The ServerAddress of the Endpoint the pool is attempting to connect to.
633 */
634 address: string;
635
636 /**
637 * The ID of the Connection
638 */
639 connectionId: number;
640 }
641
642Connection Pool Errors
643~~~~~~~~~~~~~~~~~~~~~~
644
645A connection pool throws errors in specific circumstances. These Errors
646MUST be emitted by the pool. Errors SHOULD be created and dispatched in
647a manner idiomatic to the Driver and Language.
648
649.. code:: typescript
650
651 /**
652 * Thrown when the driver attempts to check out a
653 * Connection from a closed Connection Pool
654 */
655 interface PoolClosedError {
656 message: 'Attempted to check out a connection from closed connection pool';
657 address: <pool address>;
658 }
659
660 /**
661 * Thrown when a driver times out when attempting to check out
662 * a Connection from a Pool
663 */
664 interface WaitQueueTimeoutError {
665 message: 'Timed out while checking out a connection from connection pool';
666 address: <pool address>;
667 }
668
669Test Plan
670=========
671
672See `tests/README.rst <tests/README.rst>`_
673
674Design Rationale
675================
676
677Why do we set minPoolSize across all members of a replicaSet, when most traffic will be against a Primary?
678~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
679
680Currently, we are attempting to codify our current pooling behavior with minimal changes, and minPoolSize is currently uniform across all members of a replicaSet. This has the benefit of offsetting connection swarming during a Primary Step-Down, which will be further addressed in our `Advanced Pooling Behaviors <#advanced-pooling-behaviors>`__.
681
682Why do we have separate ConnectionCreated and ConnectionReady events, but only one ConnectionClosed event?
683~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
684
685ConnectionCreated and ConnectionReady each involve different state changes in the pool.
686
687- ConnectionCreated adds a new “setting-up” connection, meaning the totalConnectionCount increases by one
688- ConnectionReady establishes that the connection is ready for use, meaning the availableConnectionCount increases by one
689
690ConnectionClosed indicates that the connection is no longer a member of the pool, decrementing totalConnectionCount and potentially availableConnectionCount. After this point, the connection is no longer a part of the pool. Further hypothetical events would not indicate a change to the state of the pool, so they are not specified here.
691
692Why are waitQueueSize and waitQueueMultiple deprecated?
693~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
694
695These options are not implemented across many drivers. Additionally, they have the effect of prioritizing older requests over newer requests, which is not necessarily the behavior that users want. They can also can result in cases where queue access oscillates back and forth instead of restricting access until the size drops. We may eventually pursue an alternative solutions in `Advanced Pooling Behaviors <#advanced-pooling-behaviors>`__.
696
697Why is waitQueueTimeoutMS optional for some drivers?
698~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
699
700We are anticipating eventually introducing a single client-side timeout mechanism, making us hesitant to introduce another granular timeout control. Therefore, if a driver/language already has an idiomatic way to implement their timeouts, they should leverage that mechanism over implementing waitQueueTimeoutMS.
701
702
703Backwards Compatibility
704=======================
705
706As mentioned in `Deprecated Options <#deprecated-options>`__, some drivers currently implement the options ``waitQueueSize`` and/or ``waitQueueMultiple``. These options will need to be deprecated and phased out of the drivers that have implemented them.
707
708
709Reference Implementations
710=========================
711
712- JAVA (JAVA-3079)
713- RUBY (RUBY-1560)
714
715Future Development
716==================
717
718SDAM
719~~~~
720
721This specification does not dictate how SDAM Monitoring connections are managed. SDAM specifies that “A monitor SHOULD NOT use the client's regular connection pool”. Some possible solutions for this include:
722
723- Having each Endpoint representation in the driver create and manage a separate dedicated Connection for monitoring purposes
724- Having each Endpoint representation in the driver maintain a separate pool of maxPoolSize 1 for monitoring purposes.
725- Having each Pool maintain a dedicated connection for monitoring purposes, with an API to expose that connection.
726
727Advanced Pooling Behaviors
728~~~~~~~~~~~~~~~~~~~~~~~~~~
729
730This spec does not address any advanced pooling behaviors like predictive pooling, aggressive connection creation, or handling high request volume. Future work may address this.
731
732Add support for OP_MSG exhaustAllowed
733~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
734
735Exhaust Cursors may require changes to how we close connections in the future, specifically to add a way to close and remove from its pool a connection which has unread exhaust messages.
736
737
738Change log
739==========
740
741:2019-06-06: Add "connectionError" as a valid reason for ConnectionCheckOutFailedEvent
View as plain text