...

Text file src/go.mongodb.org/mongo-driver/testdata/connection-monitoring-and-pooling/connection-monitoring-and-pooling.rst

Documentation: go.mongodb.org/mongo-driver/testdata/connection-monitoring-and-pooling

     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