mongodb/mongo-ruby-driver

View on GitHub
docs/reference/create-client.txt

Summary

Maintainability
Test Coverage
*****************
Creating a Client
*****************

.. default-domain:: mongodb

.. contents:: On this page
   :local:
   :backlinks: none
   :depth: 2
   :class: singlecol

Using ``Mongo::Client``
=======================

To connect to a MongoDB deployment, create a ``Mongo::Client`` object.
Provide a list of hosts and options or a :manual:`connection string URI
</reference/connection-string/>` to the``Mongo::Client`` constructor.
The client's selected database defaults to ``admin``.

By default, the driver will automatically detect the topology used by the
deployment and connect appropriately.

To connect to a local standalone MongoDB deployment, specify the host and
port of the server. In most cases you would also specify the database name
to connect to; if no database name is specified, the client will use the
``admin`` database:

.. code-block:: ruby

  Mongo::Client.new([ '127.0.0.1:27017' ], database: 'mydb')

  # Or using the URI syntax:
  Mongo::Client.new("mongodb://127.0.0.1:27017/mydb")

.. note::

  The hostname ``localhost`` is treated specially by the driver and will
  be resolved to IPv4 addresses only.

To `connect to MongoDB Atlas <https://docs.atlas.mongodb.com/driver-connection/>`_,
specify the Atlas deployment URI:

.. code-block:: ruby

  Mongo::Client.new("mongodb+srv://username:myRealPassword@cluster0.mongodb.net/mydb?w=majority")

The driver will discover all nodes in the cluster and connect to them as
needed.

Block Syntax
------------

Another way to create a Mongo::Client object is to use the block syntax:

.. code-block:: ruby

  Mongo::Client.new(...) do |client|
    # work with the client
  end

Note that when creating a client using this syntax, the client is automatically closed after the block finishes executing.

Database Selection
==================

By default, the client will connect to the ``admin`` database.

The ``admin`` database is a special database in MongoDB often used for
administrative tasks and storing administrative data such as users and
roles (although users and roles may also be defined in other databases).
In a sharded cluster, the ``admin`` database
:manual:`exists on the config servers </core/sharded-cluster-config-servers/#read-and-write-operations-on-config-servers>`
rather than the shard servers. Although it is possible to use the ``admin``
database for ordinary operations (such as storing application data), this
is not recommended and the application should explicitly specify the
database it wishes to use.

The database can be specified during ``Client`` construction:

.. code-block:: ruby

  # Using Ruby client options:
  client = Mongo::Client.new(['localhost'], database: 'mydb')

  # Using a MongoDB URI:
  client = Mongo::Client.new('mongodb://localhost/mydb')

Given a ``Client`` instance, the ``use`` method can be invoked to obtain a
new ``Client`` instance configured with the specified database:

.. code-block:: ruby

  client = Mongo::Client.new(['localhost'], database: 'mydb')

  admin_client = client.use('admin')

  # Issue an administrative command
  admin_client.database.command(replSetGetConfig: 1).documents.first

There are other special databases in MongoDB which should be only used for
their stated purposes:

- The :manual:`config </reference/config-database/>` database.
- The :manual:`local </reference/local-database/>` database.
- The ``$external`` database, which is used with :ref:`PLAIN <plain>`,
  :ref:`Kerberos <kerberos>` and :ref:`X.509 <x.509>` authentication
  mechanisms.


Connection Types
================

The driver will, by default, discover the type of deployment it is instructed
to connect to (except for load-balanced deployments)
and behave in the manner that matches the deployment type.
The subsections below describe how the driver behaves in each of the deployment
types as well as how to force particular behavior, bypassing automatic
deployment type detection.

Note that the detection of deployment type happens when the driver receives
the first reply from any of the servers it is instructed to connect to
(unless the load-balancing mode is requested, see below). The driver will
remain in the discovered or configured topology even if the underlying
deployment is replaced by one of a different type. In particular, when
replacing a replica set with a sharded cluster at the same address
the client instance must be recreated (such as by restarting the application)
for it to communicate with the sharded cluster.

Automatic discovery of load-balanced deployments is currently not supported.
Load-balanced deployments will be treated as deployments of their underlying
type, which would generally be sharded clusters. The driver will fail to
correctly operate when treating a load-balanced deployment as a sharded
cluster, therefore when the deployment is a load-balanced one the client
must be explicitly configured to :ref:`connect to a load balancer
<load-balancer-connection>`.


Standalone Server Connection
----------------------------

If the deployment is a single server, also known as a standalone deployment,
all operations will be directed to the specified server.

If the server is shut down and replaced by a replica set node, the driver
will continue sending all operations to that node, even if the node is or
becomes a secondary.

To force a standalone connection, see the :ref:`direct connection
<direct-connection>` section below.


.. _connect-replica-set:

Replica Set Connection
----------------------

When connecting to a :manual:`replica set</replication/>`, it is sufficient
to pass the address of any node in the replica set to the driver.
The node does not have to be the primary and it may be a hidden node.
The driver will then automatically discover the remaining nodes.

However, it is recommended to specify all nodes that are part of the
replica set, so that in the event of one or more nodes being unavailable
(for example, due to maintenance or reconfiguration) the driver can still
connect to the replica set.

Replica set connection examples:

.. code-block:: ruby

  Mongo::Client.new([ '127.0.0.1:27017' ], database: 'mydb')

  Mongo::Client.new([ '127.0.0.1:27017', '127.0.0.1:27018' ], database: 'mydb')

  # Or using the URI syntax:
  Mongo::Client.new("mongodb://127.0.0.1:27017,127.0.0.1:27018/mydb")

To make the driver verify the replica set name upon connection, pass it using
the ``replica_set`` Ruby option or the ``replicaSet`` URI option:

.. code-block:: ruby

  Mongo::Client.new([ '127.0.0.1:27017', '127.0.0.1:27018' ],
    database: 'mydb', replica_set: 'myapp')

  # Or using the URI syntax:
  Mongo::Client.new("mongodb://127.0.0.1:27017,127.0.0.1:27018/mydb?replicaSet=myapp")

If the deployment is not a replica set or uses a different replica set name,
all operations will fail (until the expected replica set is returned by
the servers).

It is also possible to force a replica set connection without specifying
the replica set name. Doing so is generally unnecessary and is deprecated:

.. code-block:: ruby

  Mongo::Client.new([ '127.0.0.1:27017', '127.0.0.1:27018' ],
    database: 'mydb', connect: :replica_set)

  # Or using the URI syntax:
  Mongo::Client.new("mongodb://127.0.0.1:27017,127.0.0.1:27018/mydb?connect=replica_set")

To connect to a MongoDB Atlas cluster which is deployed as a replica set,
connect to the URI:

.. code-block:: ruby

  Mongo::Client.new("mongodb+srv://username:myRealPassword@cluster0.mongodb.net/test?w=majority")

Please review the :ref:`SRV URI notes <srv-uri-notes>` if using SRV URIs.


.. _connect-sharded-cluster:

Sharded Cluster Connection
--------------------------

To connect to a :manual:`sharded cluster</sharding/>` deployment, specify
the addresses of the ``mongos`` routers:

.. code-block:: ruby

  Mongo::Client.new([ '1.2.3.4:27017', '1.2.3.5:27017' ], database: 'mydb')

  Mongo::Client.new("mongodb://1.2.3.4:27017,1.2.3.5:27017/mydb")

Note that unlike a replica set connection, you may choose to connect to a
subset of the ``mongos`` routers that exist in the deployment. The driver
will monitor each router and will use the ones that are available
(i.e., the driver will generally handle individual routers becoming
unavailable due to failures or maintenance). When specifying the list of
routers explicitly, the driver will not discover remaining routers that
may be configured and will not attempt to connect to them.

The driver will automatically balance the operation load among the routers
it is aware of.

To connect to a MongoDB Atlas cluster which is deployed as a sharded cluster,
connect to the URI:

.. code-block:: ruby

  Mongo::Client.new("mongodb+srv://username:myRealPassword@cluster0.mongodb.net/test?w=majority")

When the driver connects to a sharded cluster via an SRV URI, it will
periodically poll the SRV records of the address specified in the URI
for changes and will automatically add and remove the ``mongos`` hosts
to/from its list of servers as they are added and removed to/from the
sharded cluster.

To force a sharded cluster connection, use the ``connect: :sharded``
option. Doing so is generally unnecessary and is deprecated:

.. code-block:: ruby

  Mongo::Client.new([ '127.0.0.1:27017', '127.0.0.1:27018' ],
    database: 'mydb', connect: :sharded)

  # Or using the URI syntax:
  Mongo::Client.new("mongodb://127.0.0.1:27017,127.0.0.1:27018/mydb?connect=sharded")

Please review the :ref:`SRV URI notes <srv-uri-notes>` if using SRV URIs.


.. _direct-connection:

Direct Connection
-----------------

To disable the deployment type discovery and force all operations to be
performed on a particular server, specify the ``direct_connection`` option:

.. code-block:: ruby

  Mongo::Client.new([ '1.2.3.4:27017' ], database: 'mydb', direct_connection: true)

  # Or using the URI syntax:
  Mongo::Client.new("mongodb://1.2.3.4:27017/mydb?directConnection=true")

Alternatively, the deprecated ``connect: :direct`` option is equivalent:

.. code-block:: ruby

  Mongo::Client.new([ '1.2.3.4:27017' ], database: 'mydb', connect: :direct)

  # Or using the URI syntax:
  Mongo::Client.new("mongodb://1.2.3.4:27017/mydb?connect=direct")

The direct connection mode is most useful for performing operations on a
particular replica set node, although it also permits the underlying server
to change type (e.g. from a replica set node to a ``mongos`` router, or vice
versa).


.. _load-balancer-connection:

Load Balancer Connection
------------------------

Unlike other deployment types, the driver does not currently automatically
detect a load-balanced deployment.

To connect to a load balancer, specify the ``load_balanced: true`` Ruby option
or the ``loadBalanced=true`` URI option:

.. code-block:: ruby

  Mongo::Client.new([ '1.2.3.4:27017' ], database: 'mydb', load_balanced: true)

  # Or using the URI syntax:
  Mongo::Client.new("mongodb://1.2.3.4:27017/mydb?loadBalanced=true")

When using these options, if the specified server is not a load balancer,
the client will fail all operations (until the server becomes a load balancer).

To treat the server as a load balancer even if it doesn't identify as such,
use the ``connect: :load_balanced`` Ruby option or the ``connect=load_balanced``
URI option:

.. code-block:: ruby

  Mongo::Client.new([ '1.2.3.4:27017' ],
    database: 'mydb', load_balanced: true, connect: :load_balanced)

  # Or using the URI syntax:
  Mongo::Client.new("mongodb://1.2.3.4:27017/mydb?loadBalanced=true&connect=load_balanced")



.. _srv-uri-notes:

SRV URI Notes
=============

When the driver connects to a
:manual:`mongodb+srv protocol <reference/connection-string/#dns-seedlist-connection-format>`
URI, keep in mind the following:

1. SRV URI lookup is performed synchronously when the client is constructed.
   If this lookup fails for any reason, client construction will fail with an
   exception. When a client is constructed with a list of hosts, the driver
   will attempt to contact and monitor those hosts for as long as the client
   object exists. If one of these hosts does not resolve initially but becomes
   resolvable later, the driver will be able to establish a connection to such
   a host when it becomes available. The initial SRV URI lookup must succeed
   on the first attempt; subsequent host lookups will be retried by the driver
   as needed.
2. The driver looks up URI options in the DNS TXT records corresponding to the
   SRV records. These options can be overridden by URI options specified in the
   URI and by Ruby options, in this order.
3. Because the URI options are retrieved in a separate DNS query from the
   SRV lookup, in environments with unreliable network connectivity
   the URI option query may fail when the SRV lookup succeeds. Such a failure
   would cause the driver to use the wrong auth source leading to
   authentication failures. This can be worked around by explicitly specifying
   the auth source:

   .. code-block:: ruby

     Mongo::Client.new("mongodb+srv://username:myRealPassword@cluster0.mongodb.net/test?w=majority&authSource=admin")

4. If the topology of the constructed ``Client`` object is unknown or a
   sharded cluster, the driver will begin monitoring the specified SRV DNS
   records for changes and will automatically update the list of servers in the
   cluster. The updates will stop if the topology becomes a single or a replica
   set.


.. _client-options:

Client Options
==============

``Mongo::Client``'s constructor accepts a number of options configuring the
behavior of the driver. The options can be provided in the options hash as
Ruby options, in the URI as URI options, or both. If both a Ruby option and
the analogous URI option are provided, the Ruby option takes precedence.


Ruby Options
------------

.. note::

  The options passed directly should be symbols.

.. note::

  Unless otherwise specified, Ruby options that deal with times are given in
  seconds.

.. list-table::
   :header-rows: 1
   :widths: 25 40 10 15

   * - Option
     - Description
     - Type
     - Default

   * - ``:app_name``
     - Application name that is printed to the mongod logs upon establishing a connection
       in server versions >= 3.4.
     - ``String``
     - none

   * - ``:auth_mech``
     - Specifies the authenticaion mechanism to use. Can be one of:
       ``:gssapi``, ``:mongodb_cr``, ``:mongodb_x509``, ``:plain``,
       ``:scram``, ``:scram256``. GSSAPI (Kerberos) authentication
       :ref:`requires additional dependencies <kerberos>`.
     - ``Symbol``
     - If user credentials are not supplied, ``nil``. If user credentials
       are supplied, the default depends on server version.
       MongoDB 4.0 and later: ``:scram256`` if user credentials correspond
       to a user which supports SCRAM-SHA-256 authentication, otherwise
       ``:scram``.
       MongoDB 3.0-3.6: ``:scram``.
       MongoDB 2.6: ``:mongodb_cr``

   * - ``:auth_mech_properties``
     - Provides additional authentication mechanism properties.

       The keys in properties are interpreted case-insensitively.
       When the client is created, keys are lowercased.

     - ``Hash``
     - When using the GSSAPI authentication mechanism, the default properties
       are ``{service_name: "mongodb"}``. Otherwise the default is nil.

   * - ``:auth_source``
     - Specifies the authentication source.
     - ``String``
     - For MongoDB 2.6 and later: **admin** if credentials are
       supplied, otherwise the current database

   * - ``:auto_encryption_options``
     - A ``Hash`` of options for configuring automatic encryption.

       - ``:key_vault_client`` - A client connected to the MongoDB instance
         storing the encryption data keys (``Mongo::Client``, defaults to the
         top-level client instance).
       - ``:key_vault_namespace`` - The namespace of the key vault collection
         in the format ``"database.collection"`` (``String``, required).
       - ``:kms_providers`` - Key management service configuration information.
         One or both of the keys ``:local`` and ``:aws`` must be specified
         (``Hash``, required). See the "The ``kms_providers`` option`` section of the
         :ref:`Client-Side Encryption tutorial<client-side-encryption>` for more
         information about this option.
       - ``:schema_map`` - The JSONSchema for one or more collections specifying
         which fields should be encrypted (``Hash``, optional, defaults to ``nil``).
       - ``:bypass_auto_encryption`` - Whether to skip automatic encryption when
         performing database operations (``Boolean``, defaults to ``false``).
       - ``:extra_options`` - Options related to spawning mongocryptd (``Hash``,
         optional, defaults to ``nil``).

       For more information about formatting these options, see the
       "Auto-Encryption Options" section of the :ref:`Client-Side Encryption tutorial<client-side-encryption>`.
     - ``Hash``
     - none

   * - ``:bg_error_backtrace``
     - Experimental. Controls whether and how backtraces are logged when
       errors occur in background threads. If ``true``, the driver will log
       complete backtraces. If set to a positive integer, the driver will
       log up to that many backtrace lines. If set to ``false`` or ``nil``,
       no backtraces will be logged. Other values are an error.
     - ``true``, ``false``, ``nil``, ``Integer``
     - none

   * - ``:compressors``
     - A list of potential compressors to use, in order of preference.
       Please see below for details on how the driver implements compression.
     - ``Array<String>``
     - none

   * - ``:connect``
     - **Deprecated.** Disables deployment topology discovery normally
       performed by the dirver and forces the cluster topology to a specific
       type. Valid values are ``:direct``, ``:load_balanced``,
       ``:replica_set`` or ``:sharded``. If ``:load_balanced`` is used,
       the client will behave as if it is connected to a load balancer
       regardless of whether the server(s) it connects to advertise themselves
       as load balancers.
     - ``Symbol``
     - none

   * - ``:connect_timeout``
     - The number of seconds to wait to establish a socket connection
       before raising an exception. This timeout is also used for SRV DNS
       record resolution. ``nil`` and ``0`` mean no timeout.
       Client creation will fail with an error if an invalid timeout value
       is passed (such as a negative value or a non-numeric value).
     - ``Float``
     - 10

   * - ``:database``
     - The name of the database to connect to.
     - ``String``
     - admin

   * - ``:direct_connection``
     - Connect directly to the specified host, do not discover deployment
       topology.
     - ``Boolean``
     - false

   * - ``:heartbeat_frequency``
     - The number of seconds for the server monitors to refresh
       server states asynchronously.
     - ``Float``
     - 10

   * - ``:id_generator``
     - A custom object to generate ids for documents. Must respond to #generate.
     - ``Object``
     - none

   * - ``:load_balanced``
     - Whether to expect to connect to a load balancer.
     - ``Boolean``
     - false

   * - ``:local_threshold``
     - Specifies the maximum latency in seconds between the nearest
       server and the servers that can be available for selection to operate on.
     - ``Float``
     - 0.015

   * - ``:logger``
     - A custom logger.
     - ``Object``
     - ``Logger``

   * - ``:max_idle_time``
     - The maximum time, in seconds, that a connection can be idle before it
       is closed by the connection pool.

       *Warning:* when connected to a load balancer, the driver uses existing
       connections for iterating cursors (which includes change streams)
       and executing transactions. Setting an idle time via this option may
       cause the driver to close connections that are needed for subsequent
       operations, causing those operations to fail.
     - ``Integer``
     - none

   * - ``:max_pool_size``
     - The maximum size of the connection pool for each server.
     - ``Integer``
     - 5

   * - ``:max_read_retries``
     - The maximum number of read retries, when legacy read retries are used.
       Set to 0 to disable legacy read retries.
     - ``Integer``
     - 1

   * - ``:max_write_retries``
     - The maximum number of write retries, when legacy write retries are used.
       Set to 0 to disable legacy write retries.
     - ``Integer``
     - 1

   * - ``:min_pool_size``
     - The minimum number of connections in the connection pool for each
       server. The driver does not create connections eagerly - a connection
       is only created when a MongoDB operation is to be executed and there
       are no available connections, and the total number of established
       connections to the target server is below ``:max_pool_size``.
       However, once connections to a particular server are created, up to
       ``:min_pool_size`` connections will be kept in the connection pool
       by the driver.
     - ``Integer``
     - 0

   * - ``:monitoring``
     - The monitoring object.
     - ``Object``
     - none

   * - ``:password``
     - The password of the user to authenticate with.
     - ``String``
     - none

   * - ``:platform``
     - Platform information to include in the metadata printed to the mongod logs upon establishing a
       connection in server versions >= 3.4.
     - ``String``
     - none

   * - ``:read``
     - Specifies the read preference mode and tag sets for selecting servers
       as a ``Hash``. Allowed Keys in the hash are ``:mode``, ``:tag_sets`` and
       ``:max_staleness``.

       .. code-block:: ruby

         { read:
           { mode: :secondary,
             tag_sets: [ "data_center" => "berlin" ],
             max_staleness: 5,
           }
         }

       If tag sets are provided, they must be an array of hashes. A server
       satisfies the read preference if its tags match any one hash in the
       provided tag sets.

       Each tag set must be a hash, and will be converted internally to
       a ``BSON::Document`` instance prior to being used for server selection.
       Hash keys can be strings or symbols. The keys are case sensitive.
       Hash values must be strings, and are matched exactly against the values
       in the replica set configuration.

     - ``Hash``
     -  ``{ :mode => :primary }``

   * - ``:read_concern``
     - Specifies the read concern options. The only valid key is ``level``,
       for which the valid values are ``:local``, ``:majority``, and
       ``:snapshot``.
     - ``Hash``
     - none

   * - ``:read_retry_interval``
     - The interval, in seconds, in which reads on a mongos are retried.
     - ``Integer``
     - 5

   * - ``:replica_set``
     - When connecting to a replica set, this is the name of the set to
       filter servers by.
     - ``String``
     - none

   * - ``:retry_writes``
     - If a single-statement write operation fails from a network error, the driver automatically retries it once
       when connected to server versions 3.6+.
     - ``Boolean``
     - true

   * - ``:sdam_proc``
     - Since the client begins monitoring the deployment in background as
       soon as it is constructed, constructing a client and then subscribing
       to `SDAM <sdam>`_ events in a separate statement may result in the
       subscriber not receiving some of the SDAM events. The ``:sdam_proc``
       option permits adding event subscribers on the client being constructed
       before any SDAM events are published.

       Pass a ``Proc`` which will be called with the ``Client`` as the argument
       after the client's event subscription mechanism has been initialized
       but before any of the servers are added to the client. Use this
       ``Proc`` to set up SDAM event subscribers on the client.

       Note: the client is not fully constructed when the ``Proc`` provided in
       ``:sdam_proc is invoked, in particular the cluster is nil at this time.
       ``:sdam_proc`` procedure should limit itself to calling
       ``Client#subscribe`` and ``Client#unsubscribe`` methods on on the
       passed client only.
     - ``Proc``
     - none

   * - ``:server_api``
     - The server API version requested.
       This is a hash with the following allowed items:
       - ``:version`` (String)
       - ``:strict`` (true or false)
       - ``:deprecation_errors`` (true or false)

       Note that the server API version can only be specified as a Ruby option,
       not as a URI option, and it cannot be overridden for database and
       collection objects.

       If server API version is changed on a client (such as via the ``with``
       call), the entire API version hash is replaced with the new specification
       (the old and the new individual fields are NOT merged).
     - ``Hash``
     - none

   * - ``:server_selection_timeout``
     - The number of seconds to wait for an appropriate server to
       be selected for an operation to be executed before raising an exception.
     - ``Float``
     - 30

   * - ``:socket_timeout``
     - The number of seconds to wait for an operation to execute on a
       socket before raising an exception. ``nil`` and ``0`` mean no timeout.
       Client creation will fail with an error if an invalid timeout value
       is passed (such as a negative value or a non-numeric value).
     - ``Float``
     - none

   * - ``:srv_max_hosts``
     - The maximum number of mongoses that the driver will communicate with
       for sharded topologies. If this option is set to 0, there will
       be no maximum number of mongoses. If the given URI resolves
       to more hosts than ``:srv_max_hosts``, the client will ramdomly
       choose an ``:srv_max_hosts`` sized subset of hosts. Note that the
       hosts that the driver ignores during client construction will never
       be used. If the hosts chosen by the driver become unavailable, the
       client will quit working completely, even though the deployment has
       other functional mongoses.
     - ``Integer``
     - 0

   * - ``:srv_service_name``
     - The service name to use in the SRV DNS query.
     - ``String``
     - mongodb

   * - ``:ssl``
     - Tell the client to connect to the servers via TLS.
     - ``Boolean``
     - false

   * - ``:ssl_ca_cert``
     - The file path containing concatenated certificate authority certificates
       used to validate certs passed from the other end of the connection.
       One of ``:ssl_ca_cert``, ``:ssl_ca_cert_string`` or ``:ssl_ca_cert_object``
       (in order of priority) is required for ``:ssl_verify``.
     - ``String``
     - none

   * - ``:ssl_ca_cert_object``
     - An array of OpenSSL::X509::Certificate representing the certificate
       authority certificates used to validate certs passed from the other end
       of the connection. One of ``:ssl_ca_cert``, ``:ssl_ca_cert_string`` or
       ``:ssl_ca_cert_object`` (in order of priority) is required for ``:ssl_verify``.
     - ``Array< OpenSSL::X509::Certificate >``
     - none

   * - ``:ssl_ca_cert_string``
     - A string containing concatenated certificate authority certificates
       used to validate certs passed from the other end of the connection.
       One of ``:ssl_ca_cert``, ``:ssl_ca_cert_string`` or ``:ssl_ca_cert_object``
       (in order of priority) is required for ``:ssl_verify``.
     - ``String``
     - none

   * - ``:ssl_cert``
     - Path to the client certificate file used to identify the application to
       the MongoDB servers. The file may also contain the certificate's private
       key; if so, the private key is ignored by this option. The file may
       also contain intermediate certificates forming the certificate chain
       from the client certificate to the CA certificate; any intermediate
       certificates will be parsed by the driver and provided to the OpenSSL
       context in ``extra_chain_cert`` attribute. If intermediate certificates
       are provided, they must follow the client certificate which must be
       the first certificate in the file.

       This option, if present, takes precedence over ``:ssl_cert_string`` and
       ``:ssl_cert_object`` options.
     - ``String``
     - none

   * - ``:ssl_cert_object``
     - The OpenSSL::X509::Certificate used to identify the application to
       the MongoDB servers. Only one certificate may be passed through this
       option.
     - ``OpenSSL::X509::Certificate``
     - none

   * - ``:ssl_cert_string``
     - A string containing the PEM-encoded certificate used to identify the
       application to the MongoDB servers. The string may also contain the
       certificate's private key; if so, the private key is ignored by this
       option. The string may also contain intermediate certificates forming
       the certificate chain from the client certificate to the CA certificate;
       any intermediate certificates will be parsed by the driver and provided
       to the OpenSSL context in ``extra_chain_cert`` attribute. If intermediate
       certificates are provided, they must follow the client certificate which
       must be the first certificatet in the string.

       This option, if present, takes precedence over the ``:ssl_cert_object``
       option.
     - ``String``
     - none

   * - ``:ssl_key``
     - The private keyfile used to identify the connection against MongoDB. Note that even if the key is stored in
       the same file as the certificate, both need to be explicitly specified. This option, if present, takes
       precedence over the values of :ssl_key_string and :ssl_key_object.
     - ``String``
     - none

   * - ``:ssl_key_object``
     - The private key used to identify the connection against MongoDB.
     - ``OpenSSL::PKey``
     - none

   * - ``:ssl_key_pass_phrase``
     - A passphrase for the private key.
     - ``String``
     - none

   * - ``:ssl_key_string``
     - A string containing the PEM-encoded private key used to identify the
       connection against MongoDB. This parameter, if present, takes precedence
       over the value of option :ssl_key_object.
     - ``String``
     - none

   * - ``:ssl_verify``
     - Whether to perform peer certificate, hostname and OCSP endpoint
       validation. Note that the decision of whether to validate certificates
       will be overridden if ``:ssl_verify_certificate`` is set, the decision
       of whether to validate hostnames will be overridden if
       ``:ssl_verify_hostname`` is set and the decision of whether to validate
       OCSP endpoint will be overridden if ``:ssl_verify_ocsp_endpoint`` is set.
     - ``Boolean``
     - true

   * - ``:ssl_verify_certificate``
     - Whether to perform peer certificate validation. This setting overrides
       the ``:ssl_verify`` setting with respect to whether certificate
       validation is performed.
     - ``Boolean``
     - true

   * - ``:ssl_verify_hostname``
     - Whether to perform peer hostname validation. This setting overrides
       the ``:ssl_verify`` setting with respect to whether hostname validation
       is performed.
     - ``Boolean``
     - true

   * - ``:ssl_verify_ocsp_endpoint``
     - Whether to validate server-supplied certificate against the OCSP
       endpoint specified in the certificate, if the OCSP endpoint is specified
       in the certificate. This setting overrides :ssl_verify with respect to
       whether OCSP endpoint validation is performed.
     - ``Boolean``
     - true

   * - ``:truncate_logs``
     - Whether to truncate the logs at the default 250 characters.
     - ``Boolean``
     - true

   * - ``:user``
     - The name of the user to authenticate with.
     - ``String``
     - none

   * - ``:wait_queue_timeout``
     - The number of seconds to wait for a connection in the connection
       pool to become available.
     - ``Float``
     - 10

   * - ``:wrapping_libraries``
     - Information about libraries such as ODMs that are wrapping the driver.
       Specify the lower level libraries first. Allowed hash keys: :name,
       :version, :platform. Example: ``[name: 'Mongoid', version: '7.1.2']``
     - ``Array<Hash>``
     - none

   * - ``:write``
     - Deprecated. Equivalent to ``:write_concern`` option. If both ``:write``
       and ``:write_concern`` are specified, their values must be identical.

     - ``Hash``
     - ``{ w: 1 }``

   * - ``:write_concern``
     - Specifies write concern options as a ``Hash``.
       Keys in the hash can be ``:w``, ``:wtimeout``, ``:j``, ``:fsync``.
       Note that ``:wtimeout`` is specified in milliseconds, not seconds.

       .. code-block:: ruby

         { write_concern: { w: 2 } }

     - ``Hash``
     - ``{ w: 1 }``

   * - ``:zlib_compression_level``
     - The Zlib compression level to use, if using compression. See Ruby's Zlib module for valid levels.
     - ``Integer``
     - none

.. note::

  The Ruby driver does not implement certificate revocation list (CRL)
  checking.


URI Options
-----------

Since the URI options are required to be in camel case, which is not the Ruby
standard, the following table shows URI options and their corresponding Ruby
options.

URI options are explained in detail in the :manual:`Connection URI reference
</reference/connection-string/>`.

.. note::
  Options that are set in **milliseconds** in the URI are
  represented as a ``float`` in Ruby and the units are **seconds**.

.. list-table::
   :header-rows: 1
   :widths: 40 105

   * - URI Option
     - Ruby Option

   * - appName=String
     - ``:app_name => String``

   * - authMechanism=String
     - ``:auth_mech => Symbol``

       Auth mechanism values are converted as follows from URI options to
       Ruby options:

       - ``GSSAPI`` => ``:gssapi``
       - ``MONGODB-CR`` => ``:mongodb_cr``
       - ``MONGODB-X509`` => ``:mongodb_x509``
       - ``PLAIN`` => ``:plain``
       - ``SCRAM-SHA-1`` => ``:scram``
       - ``SCRAM-SHA-256`` => ``:scram256``

       If a different value is provided for auth mechanism, it is converted
       to the Ruby option unmodified and retains its ``String`` type.
       Note that, while currently the driver allows a ``Client`` instance
       to be constructed with an unrecognized auth mechanism, this behavior
       `may change in a future version of the driver <https://jira.mongodb.org/browse/RUBY-1745>`_.

   * - authMechanismProperties=Strings
     - ``{ :auth_mech_properties => { :service_realm => String, :canonicalize_host_name => true|false, :service_name => String } }``

       Specified as comma-separated key:value pairs, e.g. ``"SERVICE_REALM:foo,CANONICALIZE_HOST_NAME:TRUE"``.

   * - authSource=String
     - ``:auth_source => String``

   * - compressors=Strings
     - ``:compressors => Array<String>``

       A comma-separated list of potential compressors to use, in order of
       preference. Please see below for details on how the driver implements
       compression.

   * - connect=String
     - ``:connect => Symbol``

       The same values that the ``:connect`` Ruby option accepts are
       accepted here. For multi-word values, the values must be provided
       using underscores to separate the words, i.e.
       ``connect=replica_set`` and ``connect=load_balanced``.

   * - connectTimeoutMS=Integer
     - ``:connect_timeout => Float``

       Unlike the corresponding Ruby option which fails client creation on
       invalid values (e.g. negative and non-numeric values), invalid values
       provided via this URI option are ignored with a warning.

   * - directConnection=Boolean
     - ``:direct_connection => Boolean``

   * - fsync=Boolean
     - ``{ :write_concern => { :fsync => true|false }}``

   * - heartbeatFrequencyMS=Integer
     - ``:heartbeat_frequency => Float``

   * - journal=Boolean
     - ``{ :write_concern => { :j => true|false }}``

   * - loadBalanced=Boolean
     - ``:load_balanced => Boolean``

   * - localThresholdMS=Integer
     - ``:local_threshold => Float``

   * - maxIdleTimeMS=Integer
     - ``:max_idle_time => Float``

   * - maxStalenessSeconds=Integer
     - ``{ :read => { :max_staleness => Integer }}``

       If the maxStalenessSeconds URI option value is -1, the driver treats
       this as if the option was not given at all. Otherwise,
       if the option value is numeric, the Ruby option is set to the
       specified value converted to an ``Integer``.
       Note that numeric values greater than 0 but less than 90, or less than
       -1, are accepted by the ``Client`` constructor but will cause server
       selection to fail (unless the option is changed via, for example, the
       ``with`` method prior to any operations being performed on the driver).
       If the option value is non-numeric, it is ignored and the driver
       treats this case as if the option was not given at all.

   * - maxPoolSize=Integer
     - ``:max_pool_size => Integer``

   * - minPoolSize=Integer
     - ``:min_pool_size => Integer``

   * - readConcernLevel=String
     - ``:read_concern => Hash``

   * - readPreference=String
     - ``{ :read => { :mode => Symbol }}``

   * - readPreferenceTags=Strings
     - ``{ :read => { :tag_sets => Array<Hash> }}``

       Each instance of the readPreferenceTags field is a comma-separated key:value pair which will appear in the :tag_sets array in the order they are specified. For instance, ``"readPreferenceTags=dc:ny,rack:1&readPreferenceTags=dc:ny"`` will be converted to ``[ { 'dc' => 'ny', 'rack' => '1' }, { 'dc' => 'ny' }]``.

   * - replicaSet=String
     - ``:replica_set => String``

   * - retryWrites=Boolean
     - ``:retry_writes => boolean``

   * - serverSelectionTimeoutMS=Integer
     - ``:server_selection_timeout => Float``

   * - socketTimeoutMS=Integer
     - ``:socket_timeout => Float``

       Unlike the corresponding Ruby option which fails client creation on
       invalid values (e.g. negative and non-numeric values), invalid values
       provided via this URI option are ignored with a warning.

  * - srvMaxHosts=Integer
    - ``:srv_max_hosts => Integer``

  * - srvServiceName=String
    - ``:srv_service_name => String``

   * - ssl=Boolean
     - ``:ssl => true|false``

   * - tls=Boolean
     - ``:ssl => boolean``

   * - tlsAllowInvalidCertificates=Boolean
     - ``:ssl_verify_certificate => boolean``

       Because ``tlsAllowInvalidCertificates`` uses ``true`` to signify that
       verification should be disabled and ``ssl_verify_certificate`` uses
       ``false`` to signify that verification should be disabled, the boolean
       is inverted before being used to set ``ssl_verify_certificate``.

   * - tlsAllowInvalidHostnames=Boolean
     - ``:ssl_verify_hostname => boolean``

       Because ``tlsAllowInvalidHostnames`` uses ``true`` to signify that
       verification should be disabled and ``ssl_verify_hostname`` uses
       ``false`` to signify that verification should be disabled, the boolean
       is inverted before being used to set ``ssl_verify_hostname``.

   * - tlsCAFile=String
     - ``:ssl_ca_cert => String``

   * - tlsCertificateKeyFile=String
     - ``:ssl_cert => String``

   * - tlsCertificateKeyFile=String
     - ``:ssl_key => String``

   * - tlsCertificateKeyFilePassword=String
     - ``:ssl_key_pass_phrase => String``

   * - tlsDisableOCSPEndpointCheck=Boolean
     - ``:ssl_verify_ocsp_endpoint => boolean``

       Because ``tlsDisableOCSPEndpointCheck`` uses ``true`` to signify that
       verification should be disabled and ``ssl_verify_ocsp_endpoint`` uses
       ``false`` to signify that verification should be disabled, the boolean
       is inverted before being used to set ``ssl_verify_ocsp_endpoint``.

   * - tlsInsecure=Boolean
     - ``:ssl_verify => boolean``

       Because tlsInsecure uses ``true`` to signify that verification should
       be disabled and ``ssl_verify`` uses ``false`` to signify that
       verification should be disabled, the boolean is inverted before being
       used to set ``ssl_verify``.

   * - w=Integer|String
     - ``{ :write_concern => { :w => Integer|String }}``

   * - waitQueueTimeoutMS=Integer
     - ``:wait_queue_timeout => Float``

   * - wtimeoutMS=Integer
     - ``{ :write_concern => { :wtimeout => Integer }}``

   * - zlibCompressionLevel=Integer
     - ``:zlib_compression_level => Integer``

.. note::

  The Ruby driver only fails connections when it receives a definitive signed
  response indicating that the server's certificate has been revoked.
  Because of this, the driver does not recognize the
  ``tlsDisableCertificateRevocationCheck`` URI option. If this option is
  provided in a URI, it will be ignored.


Timeout Options
===============

``server_selection_timeout``
----------------------------

When executing an operation, the number of seconds to wait for the driver
to find an appropriate server to send an operation to. Defaults to 30.

A value of 0 means no timeout.

When an invalid value (e.g. a negative value or a non-numeric value) is passed
via the URI option, the invalid input is ignored with a warning. When an
invalid value is passed directly to Client via a Ruby option, Client
construction fails with an error.

In replica set deployments, this timeout should be set to exceed the typical
:manual:`replica set election times </core/replica-set-elections/>`
in order for the driver to transparently handle primary changes. This timeout
also allows the application and the database to be started simultaneously;
the application will wait up to this much time for the database to become
available.

If the application server is behind a reverse proxy, server selection timeout
should be lower than the request timeout configured on the reverse proxy (for
example, this applies to deployments on Heroku which has a fixed 30 second
timeout in the routing layer). In development this value can be lowered to
provide quicker failure when the server is not running.

``socket_timeout``
------------------

The number of seconds to wait for a socket read or write to complete on
regular (non-monitoring) connections. Default is no timeout.

A value of 0 means no timeout.

When an invalid value (e.g. a negative value or a non-numeric value) is passed
via the URI option, the invalid input is ignored with a warning. When an
invalid value is passed directly to Client via a Ruby option, Client
construction fails with an error.

This timeout should take into account both network latency and operation
duration. For example, setting this timeout to 5 seconds will abort queries
taking more than 5 seconds to execute on the server with ``Mongo::Error::SocketTimeoutError``.

Note that even though by default there is no socket timeout set, the
operating system may still time out read operations depending on its
configuration. The keepalive settings are intended to detect broken network
connections (as opposed to aborting operations simply because they take a
long time to execute).

Note that if an operation is timed out by the driver due to exceeding the
``socket_timeout`` value, it is not aborted on the server. For this reason
it is recommended to use ``max_time_ms`` option for potentially long running
operations, as this will abort their execution on the server.

This option does not apply to monitoring connections.

``connect_timeout``
-------------------

The number of seconds to wait for a socket connection to be established to
a server. Defaults to 10.

This timeout is also used as both connect timeout and socket timeout for
monitoring connections.

When using a ``mongodb+srv://`` URI, this timeout is also used for SRV and TXT
DNS lookups. Note that the timeout applies per lookup; due to DNS suffix search
lists, multiple lookups may be performed as part of a single name resolution.

``wait_queue_timeout``
``````````````````````

The number of seconds to wait for a connection in the connection pool to
become available. Defaults to 10.

As of driver version 2.11, this timeout should be set to a value at least
as large as ``connect_timeout`` because connection pool now fully establishes
connections prior to returning them, which may require several network
round trips.

``max_time_ms``
---------------

Specified as an option on a particular operation, the number of milliseconds
to allow the operation to execute for on the server. Not set by default.

Consider using this option instead of a ``socket_timeout`` for potentially
long running operations to be interrupted on the server when they take too
long.

``wtimeout``
------------

The number of milliseconds to wait for a write to be acknowledged by the
number of servers specified in the write concern. Not set by default, which
instructs the server to apply its default. This option can be set globally
on the client or passed to individual operations under ``:write_concern``.


TLS Connections
===============

To connect to the MongoDB deployment using TLS:

- Enable TLS connections in ``Mongo::Client``.
- Specify the client TLS certificate.
- Specify the CA certificate to verify the server's TLS certificate.

.. note::

  When using JRuby, ECDSA certificates are not currently supported.

TLS vs SSL Option Names
-----------------------

All MongoDB server versions supported by the Ruby driver (2.6 and higher)
only implement TLS. 2.6 and higher servers do not use SSL.

For historical reasons, the Ruby option names pertaining to TLS configuration
use the ``ssl`` rather than the ``tls`` prefix. The next major version of
the Ruby driver (3.0) will use the ``tls`` prefix for Ruby option names.

The URI option names use the ``tls`` prefix, with one exception: there is
a ``ssl`` URI option that is deprecated and equivalent to the ``tls`` URI
option.

Enable TLS Connections
----------------------

TLS must be explicitly requested on the client side when the deployment
requires TLS connections - there is currently no automatic detection of
whether the deployment requires TLS.

To request TLS connections, specify the following client options when
constructing a ``Mongo::Client``:

- The ``:ssl`` Ruby option.
- The ``tls`` URI option.
- The ``ssl`` URI option (deprecated).

Specify Client TLS Certificate
------------------------------

By default, MongoDB server will attempt to verify the connecting clients'
TLS certificates, which requires the clients to specify their TLS certificates
when connecting. This can be accomplished via:

- The ``:ssl_cert``/``:ssl_cert_object``/``:ssl_cert_string`` and
  ``:ssl_key``/``:ssl_key_object``/``:ssl_key_string``/``:ssl_key_pass_phrase``
  Ruby options.
- The ``tlsCertificateKeyFile`` URI option.

When using the Ruby options, the client TLS certificate and the corresponding
private key may be provided separately. For example, if the certificate is
stored in ``client.crt`` and the private key is stored in ``client.key``,
a ``Mongo::Client`` may be constructed as follows:

.. code-block:: ruby

    client = Mongo::Client.new(["localhost:27017"],
      ssl: true,
      ssl_cert: 'path/to/client.crt',
      ssl_key: 'path/to/client.key',
      ssl_ca_cert: 'path/to/ca.crt',
    )

``ssl_cert``, ``ssl_cert_string``, ``ssl_key`` and ``ssl_key_string`` Ruby
options also permit the certificate and the key to be provided in the same
file or string, respectively. The files containing both certificate and
private key frequently have the ``.pem`` extension. When both certificate
and the private key are provided in the same file or string, both the
certifcate and the key options must be utilized, as follows:

.. code-block:: ruby

    client = Mongo::Client.new(["localhost:27017"],
      ssl: true,
      ssl_cert: 'path/to/client.pem',
      ssl_key: 'path/to/client.pem',
      ssl_ca_cert: 'path/to/ca.crt',
    )

When using the URI option, the certificate and the key must be stored in a
file and both must be stored in the same file. Example usage:

.. code-block:: ruby

    client = Mongo::Client.new(
      "mongodb://localhost:27017/?tls=true&tlsCertificateKeyFile=path%2fto%2fclient.pem&tlsCertificateKeyFile=path%2fto%2fca.crt")

.. note::

  URI option values must be properly URI escaped. This applies, for example, to
  slashes in the paths.


.. _modifying-tls-context:

Modifying ``SSLContext``
------------------------
It may be desirable to further configure TLS options in the driver, for example
by enabling or disabling certain ciphers. Currently, the Ruby driver does not
provide a way to do this when initializing a ``Mongo::Client``.

However, the Ruby driver provides a way to set global "TLS context hooks" --
these are user-provided ``Proc``s that will be invoked before any TLS socket
connection and can be used to modify the underlying ``OpenSSL::SSL::SSLContext``
object used by the socket.

To set the TLS context hooks, add ``Proc``s to the ``Mongo.tls_context_hooks``
array. This should be done before creating any Mongo::Client instances.
For example, in a Rails application this code could be placed in an initializer.

.. code-block:: ruby

  Mongo.tls_context_hooks.push(
    Proc.new { |context|
      context.ciphers = ["AES256-SHA"]
    }
  )

  # Only the AES256-SHA cipher will be enabled from this point forward

Every ``Proc`` in ``Mongo.tls_context_hooks`` will be passed an
``OpenSSL::SSL::SSLContext`` object as its sole argument. These ``Proc``s will
be executed sequentially during the creation of every ``Mongo::Socket::SSL`` object.

It is possible to assign the entire array of hooks calling ``Mongo.tls_context_hooks=``,
but doing so will remove any previously assigned hooks. It is recommended to use
the ``Array#push`` or ``Array#unshift`` methods to add new hooks.

It is also possible to remove hooks from ``Mongo.tls_context_hooks`` by storing
a reference to the Procs somewhere else in the application, and then using
``Array#delete_if`` to remove the desired hooks.

..warning ::

  TLS context hooks are global and will affect every instance of ``Mongo::Client``.
  Any library that allows applications to enable these hooks should expose methods to
  modify the hooks (which can be called by the application) rather than
  automatically enabling the hooks when the library is loaded.

Further information on configuring MongoDB server for TLS is available in the
:manual:`MongoDB manual </tutorial/configure-ssl/>`.

Using Intermediate Certificates
```````````````````````````````

It is possible to use certificate chains for both the client and the server
certificates. When using chains, the certificate authority parameter should
be configured to contain the trusted root certificates only; the intermediate
certificates, if any, should be provided in the server or client certificates
by concatenating them after the leaf server and client certificates, respectively.

``:ssl_cert`` and ``:ssl_cert_string`` Ruby options, as well as
``tlsCertificateKeyFile`` URI option, support certificate chains.
``:ssl_cert_object`` Ruby option, which takes an instance of
``OpenSSL::X509::Certificate``, does not support certificate chains.

The Ruby driver performs strict X.509 certificate verification, which requires
that both of the following fields are set in the intermediate certificate(s):

- X509v3 Basic Constraints: CA: TRUE -- Can sign certificates
- X509v3 Key Usage: Key Cert Sign -- Can sign certificates

More information about these flags can be found `in this Stack Overflow question
<https://stackoverflow.com/questions/5795256/what-is-the-difference-between-the-x-509-v3-extensions-basic-constraints-and-key>`_.

It is a common pitfall to concatenate intermediate certificates to the root
CA certificates passed in ``tlsCAFile`` / ``ssl_ca_cert`` options. By doing
so, the intermediate certificates are elevated to trusted status and are
themselves not verified against the actual CA root. More information on this
issue is available `in this mailing list post
<https://mail.python.org/pipermail/cryptography-dev/2016-August/000676.html>`_.

Specify CA Certificate
----------------------

The driver will attempt to verify the server's TLS certificate by default, and
will abort the connection if this verification fails. By default, the driver
will use the default system root certificate store as the trust anchor.
To specify the CA certificate that the server's certificate is signed with,
use:

- The ``:ssl_ca_cert``/``:ssl_ca_cert_string``/``:ssl_ca_cert_object``
  Ruby options
- The ``tlsCAFile`` URI option.

If any of these options are given, the server's certificate will be verified
only against the specified CA certificate and the default system root
certificate store will not be used.

To not perform server TLS certificate verification, which is not
recommended, specify the ``ssl_verify: false`` Ruby option or the
``tlsInsecure=true`` URI option.

Specifying Multiple CA Certificates
```````````````````````````````````

The ``:ssl_ca_cert`` Ruby option and ``tlsCAFile`` URI option can be used with
a file containing multiple certificates. All certificates thus referenced
will become trust anchors.

The ``:ssl_ca_cert_object`` option takes an array of certificates, and thus
can also be used to add multiple certificates as certificate authorities.

The ``:ssl_ca_cert_string`` option supports specifying only one CA certificate.

.. warning::

  Intermediate certificates must not be provided in files specified by the
  CA certificate options. Doing so would elevate the intermediate certificates
  to the status of root certificates, rather than verifying intermediate
  certificates against the root certificates.

  If intermediate certificates need to be used, specify them as part of the
  client or server TLS certificate files.


.. _ocsp-verification:

OCSP Verification
-----------------

If the certificate provided by the server contains an OCSP endpoint URI,
the driver will issue an OCSP request to the specified endpoint to verify the
validity of the certificate.

The OCSP endpoint check may be disabled by setting the
``:ssl_verify_ocsp_endpoint`` Ruby option to ``false`` or by setting the
``tlsDisableOCSPEndpointCheck`` URI option to ``true`` when creating a client.

.. note::

  OCSP endpoint checking is not currently performed when running on JRuby,
  since JRuby does not correctly expose the OCSP endpoint URI.


IPv4/IPv6 Connections
=====================

When a client is constructed with ``localhost`` as the host name, it will
attempt an IPv4 connection only (i.e. if ``localhost`` resolves to
``127.0.0.1`` and ``::1``, the driver will only try to connect to
``127.0.0.1``).

When a client is constructed with hostnames other than ``localhost``, it will
attempt both IPv4 and IPv6 connections depending on the addresses that the
hostnames resolve to. The driver respects the order in which ``getaddrinfo``
returns the addresses, and will attempt to connect to them sequentially.
The first successful connection will be used.

The driver does not currently implement the Happy Eyeballs algorithm.


TCP Keepalive Configuration
===========================

Where allowed by system configuration and the Ruby language runtime,
the driver enables TCP keepalive and, for each of the keepalive parameters
listed below, sets the value of the respective parameter to the specified
value if the system value can be determined and is higher than the
listed driver value:

- ``tcp_keepalive_time``: 120 seconds
- ``tcp_keepalive_intvl``: 10 seconds
- ``tcp_keepalive_cnt``: 9 probes

.. note::

  As of JRuby 9.2.14.0, JRuby does not implement the APIs required to
  set the keepalive parameters. When using JRuby, the driver will not be
  able to set the keepalive parameters and the system configuration will
  be in effect.

To use lower values, or to change the parameters in environments like JRuby
that do not expose the required APIs, please adjust the parameters at the
system level as described in the `MongoDB Diagnostics FAQ keepalive section
<https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#serverselectiontimeoutms>`_.


Connection Pooling
==================

``Mongo::Client`` instances have a connection pool per server that the client
is connected to. The pool creates connections on demand to support concurrent
MongoDB operations issued by the application. There is no thread-affinity
for connections.

The client instance opens one additional connection per known server
for monitoring the server's state.

The size of each connection pool is capped at ``max_pool_size``, which defaults
to 5. When a thread in the application begins an operation on MongoDB, it tries
to retrieve a connection from the pool to send that operation on. If there
are some connections available in the pool, it checks out a connection from
the pool and uses it for the operation. If there are no connections available
and the size of the pool is less than the ``max_pool_size``, a new connection
will be created. If all connections are in use and the pool has reached its
maximum size, the thread waits for a connection to be returned to the pool by
another thread.

The number of seconds the thread will wait for a connection to become available
is configurable. This setting, called ``wait_queue_timeout``, is defined in
seconds. If this timeout is reached, a ``Timeout::Error`` is raised. The
default is 1 second.

As of driver version 2.11, the driver eagerly creates connections up to
``min_pool_size`` setting. Prior to driver version 2.11, the driver always
created connections on demand. In all versions of the driver, once a connection
is established, it will be kept in the pool by the driver as long as the pool
size does not exceed ``min_pool_size``.

Note that, if ``min_pool_size`` is set to a value greater than zero, the
driver will establish that many connections to secondaries in replica set
deployments even if the application does not perform secondary reads. The
purpose of these connections is to provide faster failover when the primary
changes.

Here is an example of estimating the number of connections a multi-threaded
application will open: A client connected to a 3-node replica set opens 3
monitoring sockets. It also opens as many sockets as needed to support a
multi-threaded application's concurrent operations on each server, up to
``max_pool_size``. If the application only uses the primary (the default),
then only the primary connection pool grows and the total connections is at
most 8 (5 connections for the primary pool + 3 monitoring connections).
If the application uses a read preference to query the secondaries, their
pools also grow and the total connections can reach 18 (5 + 5 + 5 + 3).

The default configuration for a ``Mongo::Client`` works for most applications:

.. code-block:: ruby

    client = Mongo::Client.new(["localhost:27017"])

Create this client **once** for each process, and reuse it for all operations.
It is a common mistake to create a new client for each request, which is very
inefficient and not what the client was designed for.

To support extremely high numbers of concurrent MongoDB operations within one
process, increase ``max_pool_size``:

.. code-block:: ruby

    client = Mongo::Client.new(["localhost:27017"], max_pool_size: 200)

Any number of threads are allowed to wait for connections to become available,
and they can wait the default (1 second) or the ``wait_queue_timeout`` setting:

.. code-block:: ruby

    client = Mongo::Client.new(["localhost:27017"], wait_queue_timeout: 0.5)

When ``#close`` is called on a client by any thread, all connections are closed:

.. code-block:: ruby

    client.close

Note that when creating a client using the `block syntax <#block-syntax>`_ described above, the client is automatically closed after the block finishes executing.

.. _forking:

Usage with Forking Servers
==========================

.. note::

  Applications using Mongoid should follow `Mongoid's forking guidance
  <https://mongodb.com/docs/mongoid/current/tutorials/mongoid-configuration/#usage-with-forking-servers>`_.
  The guidance and sample code below is provided for applications using the
  Ruby driver directly.

When using the Mongo Ruby driver in a Web application with a forking web server
such as Unicorn, Puma or Passenger, or when the application otherwise forks,
each process should generally each have their own ``Mongo::Client`` instances.
This is because:

1. The background threads remain in the parent process and are not transfered
   to the child process.
2. File descriptors like network sockets are shared between parent and
   child processes.

The driver attempts to detect client use from forked processes and
reestablish network connections when such use is detected, alleviating
the issue of file descriptor sharing.

If both parent and child processes need to perform MongoDB operations,
it is recommended for each of the processes to create their own
``Mongo::Client`` instances. Specifically, the child process should create
its own client instance and not use any of the instances that were created
in the parent.

If the parent continues to perform MongoDB operations using an already
established client instance after forking children, this client instance will
continue to operate normally as long as no child uses it in any way.
The child processes will not inherit any of the monitoring threads, and
will not perform background operations on the client instance.

If the parent does not need to perform MongoDB operation after forking
children (which is what typically happens in web applications), the parent
should close all of the client instances it created to free up connections
and cease background monitoring:

.. code-block:: ruby

  client.reconnect

.. note::

  If the parent process performs operations on the Mongo client and does not
  close it, the parent process will continue consuming a connection slot
  in the cluster and will continue monitoring the cluster for as long as the
  parent remains alive.

Reconnecting Client Instances
-----------------------------

When the Ruby driver is used in a web application, it is recommended to not
create any ``Mongo::Client`` instances in the management processes (prior to
the workers being forked), and instead only create client instances in the
workers.

It is possible, although not recommended, to use the same ``Mongo::Client``
instances in parent and child processes. In order to do so, the instance
must be closed and reconnected in the child process so that the background
threads can be recreated:

.. code-block:: ruby

  client.close
  client.reconnect

.. note::

  This pattern should be used with Ruby driver version 2.6.2 or higher.
  Previous driver versions did not recreate monitoring threads when
  reconnecting.

.. note::

  When closing and reconnecting the client instance in the child,
  due to file descriptor sharing, the parent process may experience network
  and monitoring errors.

Web servers generally provide hooks that can be used by applications to
perform actions when the worker processes are forked. The recommended hooks
to use are:

- For `Puma <https://puma.io/puma/>`_, ``before_fork`` to close clients in the
  parent process and ``on_worker_boot`` to reconnect in the child processes.
- For `Unicorn <https://yhbt.net/unicorn/Unicorn/Configurator.html>`_,
  ``before_fork`` to close clients in the parent process and
  ``after_fork`` to reconnect clients in the child processes.
- For `Passenger <https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/#unintentional-file-descriptor-sharing>`_,
  ``starting_worker_process`` to reconnect clients in the child processes
  (Passenger does not appear to have a pre-fork hook).

This documentation does not provide example code for using the aforementioned
hooks, because there is no standard for client instance management when
using the Ruby driver directly. `Mongoid documentation
<https://mongodb.com/docs/mongoid/current/tutorials/mongoid-configuration/#usage-with-forking-servers>`_
however provides examples for closing clients in the parent process and
reconnecting clients in the child processes.

Troubleshooting
---------------

The client's ``summary`` method returns the current state of the client,
including servers that the client is monitoring and their state. If any of
the servers are not being monitored, this is indicated by the ``NO-MONITORING``
flag.

A normally operating client will produce a summary similar to the following:

.. code-block:: ruby

  client.summary
  => "#<Client cluster=#<Cluster
    topology=ReplicaSetWithPrimary[localhost:14420,localhost:14421,localhost:14422,localhost:14423,name=ruby-driver-rs,v=1,e=7fffffff000000000000001f]
    servers=[#<Server address=localhost:14420 PRIMARY replica_set=ruby-driver-rs pool=#<ConnectionPool size=0 (0-5) used=0 avail=0 pending=0>>,
      #<Server address=localhost:14421 SECONDARY replica_set=ruby-driver-rs pool=#<ConnectionPool size=0 (0-5) used=0 avail=0 pending=0>>,
      #<Server address=localhost:14422 SECONDARY replica_set=ruby-driver-rs pool=#<ConnectionPool size=0 (0-5) used=0 avail=0 pending=0>>,
      #<Server address=localhost:14423 ARBITER replica_set=ruby-driver-rs>]>>"

A client that is missing background threads will produce a summary similar to
the following:

.. code-block:: ruby

  client.summary
  => "#<Client cluster=#<Cluster
    topology=ReplicaSetWithPrimary[localhost:14420,localhost:14421,localhost:14422,localhost:14423,name=ruby-driver-rs,v=1,e=7fffffff000000000000001f]
    servers=[#<Server address=localhost:14420 PRIMARY replica_set=ruby-driver-rs NO-MONITORING pool=#<ConnectionPool size=0 (0-5) used=0 avail=0 pending=0>>,
      #<Server address=localhost:14421 SECONDARY replica_set=ruby-driver-rs NO-MONITORING pool=#<ConnectionPool size=0 (0-5) used=0 avail=0 pending=0>>,
      #<Server address=localhost:14422 SECONDARY replica_set=ruby-driver-rs NO-MONITORING pool=#<ConnectionPool size=0 (0-5) used=0 avail=0 pending=0>>,
      #<Server address=localhost:14423 ARBITER replica_set=ruby-driver-rs>]>>"


Retryable Reads
===============

The driver implements two mechanisms for retrying reads: modern and legacy.
As of driver version 2.9.0, the modern mechanism is used by default, and the
legacy mechanism is deprecated.

Modern Retryable Reads
----------------------

When the modern mechanism is used, read operations are retried once in the
event of a network error, a "not master" error, or a "node is recovering" error.
The following operations are covered:

- `Collection#find <http://api.mongodb.com/ruby/current/Mongo/Collection.html#find-instance_method>`_
  and related methods
- `Collection#aggregate <http://api.mongodb.com/ruby/current/Mongo/Collection.html#aggregate-instance_method>`_
- `Collection#count <http://api.mongodb.com/ruby/current/Mongo/Collection.html#count-instance_method>`_,
  `Collection#count_documents <http://api.mongodb.com/ruby/current/Mongo/Collection.html#count_documents-instance_method>`_
- Change stream helpers: `Collection#watch <http://api.mongodb.com/ruby/current/Mongo/Collection.html#watch-instance_method>`_,
  `Database#watch <http://api.mongodb.com/ruby/current/Mongo/Database.html#watch-instance_method>`_,
  `Client#watch <http://api.mongodb.com/ruby/current/Mongo/Client.html#watch-instance_method>`_
- Enumeration commands: `Client#list_mongo_databases <http://api.mongodb.com/ruby/current/Mongo/Client.html#list_mongo_databases-instance_method>`_,
  `Client#list_databases <http://api.mongodb.com/ruby/current/Mongo/Client.html#list_databases-instance_method>`_,
  `Client#database_names <http://api.mongodb.com/ruby/current/Mongo/Client.html#database_names-instance_method>`_,
  `Database#collection_names <http://api.mongodb.com/ruby/current/Mongo/Database.html#collection_names-instance_method>`_,
  `Database#collections <http://api.mongodb.com/ruby/current/Mongo/Database.html#collections-instance_method>`_,
  `Database#list_collections <http://api.mongodb.com/ruby/current/Mongo/Database.html#list_collections-instance_method>`_,
  `Collection#indexes <http://api.mongodb.com/ruby/current/Mongo/Collection.html#indexes-instance_method>`_

When an operation returns a cursor, only the initial read command can be retried.
``getMore`` operations on cursors are not retried by driver version 2.9.0 or
newer. Additionally, when a read operation is retried, a new server for the
operation is selected; this may result in the retry being sent to a different
server from the one which received the first read.

The behavior of modern retryable reads is covered in detail by the
`retryable reads specification
<https://github.com/mongodb/specifications/blob/master/source/retryable-reads/retryable-reads.rst>`_.

Note that the modern retryable reads can only be used with MongoDB 3.6 and
higher servers. When used with MongoDB 3.4 and lower servers, Ruby driver
version 2.9.0 and higher will not retry reads by default - the application
must explicitly request legacy retryable reads by setting the
``retry_reads: false`` client option or using ``retryReads=false`` URI option.

Legacy Retryable Reads
----------------------

The legacy read retry behavior of the Ruby driver is available by setting the
``retry_reads: false`` client option or passing the ``retryReads=false`` URI
option to the client.

When using legacy read retry behavior, the number of retries can be set
by specifying the ``max_read_retries`` client option. When using driver version
2.9.0 or higher, the set of operations which would be retried with legacy
retryable reads is identical to the one described above for modern retryable
reads. In older driver versions the behavior of legacy retryable writes was
different in that some of the operations were not retried.

As of driver version 2.9.0, legacy read retries perform server selection prior
to retrying the operation, as modern retriable writes do. In older driver
versions read retries would be sent to the same server which the initial read
was sent to.

Disabling Retryable Reads
-------------------------

To disable all read retries, set the following client options:
``retry_reads: false, max_read_retries: 0``.


Retryable Writes
================

The driver implements two mechanisms for retrying writes: modern and legacy.
As of driver version 2.9.0, the modern mechanism is used by default on servers
that support it, and the legacy mechanism is deprecated and disabled by default
on all server versions.

The following write methods used in day-to-day operations on collections
are subject to write retries:

- ``collection#insert_one``
- ``collection#update_one``
- ``collection#delete_one``
- ``collection#replace_one``
- ``collection#find_one_and_update``
- ``collection#find_one_and_replace``
- ``collection#find_one_and_delete``
- ``collection#bulk_write`` (for all single statement ops, i.e. not for ``update_many`` or ``delete_many``)

Modern Retryable Writes
-----------------------

The modern mechanism will retry failing writes once when the driver is
connected to a MongoDB 3.6 or higher replica set or a sharded cluster,
because they require an oplog on the serer. Modern mechanism will not retry
writes when the driver is connected to a standalone MongoDB server or
server versions 3.4 or older.

The following errors will cause writes to be retried:

- Network errors including timeouts
- "not master" errors
- "node is recovering" errors

Prior to retrying the write the driver will perform server selection,
since the server that the original write was sent to is likely no longer
usable.

Legacy Retryable Writes
-----------------------

If modern retryable writes mechanism is disabled by setting the client
option ``retry_writes: false`` or by using the ``retryWrites=false``
URI option, the driver will utilize the legacy retryable writes mechanism.
The legacy mechanism retries writes on the same operations as the modern
mechanism. By default the legacy mechanism retries once, like the modern
mechanism does; to change the number of retries, set ``:max_write_retries``
client option.

The difference between legacy and modern retry mechanisms is that the
legacy mechanism retries writes for a different set
of errors compared to the modern mechanism, and specifically does not
retry writes when a network timeout is encountered.

Disabling Retryable Writes
--------------------------

To disable all write retries, set the following client options:
``retry_writes: false, max_write_retries: 0``.

Logging
=======

You can either use the default global driver logger or set your own. To set your own:

.. code-block:: ruby

  Mongo::Logger.logger = other_logger

See the `Ruby Logger documentation <http://ruby-doc.org/stdlib-2.2.0/libdoc/logger/rdoc/Logger.html>`_
for more information on the default logger API and available levels.

Changing the Logger Level
-------------------------

To change the logger level:

.. code-block:: ruby

  Mongo::Logger.logger.level = Logger::WARN

For more control, a logger can be passed to a client for per-client control over logging.

.. code-block:: ruby

  my_logger = Logger.new(STDOUT)
  Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'test', :logger => my_logger )

Truncation
----------

The default logging truncates logs at 250 characters by default. To turn this off pass an
option to the client instance.

.. code-block:: ruby

  Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'test', :truncate_logs => false )


.. _compression:

Compression
===========

To use wire protocol compression, at least one compressor must be explicitly
requested using either the ``:compressors`` Ruby option or the ``compressors``
URI option. If no compressors are explicitly requested, the driver will not
use compression, even if the required dependencies for one or more compressors
are present on the system.

The driver chooses the first compressor of the ones requested that is also
supported by the server. The driver currently supports ``zstd``, ``snappy`` and
``zlib`` compressors. ``zstd`` compressor is recommended as it produces
the highest compression at the same CPU consumption compared to the other
compressors. For maximum server compatibility all three compressors can be
specified, e.g. as ``compressors: ["zstd", "snappy", "zlib"]``.

``zstd`` compressor requires the
`zstd-ruby <https://rubygems.org/gems/zstd-ruby>`_ library to be installed.
``snappy`` compressor requires the
`snappy <https://rubygems.org/gems/snappy>`_ library to be installed.
If ``zstd`` or ``snappy`` compression is requested, and the respective
library is not loadable, the driver will raise an error during
``Mongo::Client`` creation. ``zlib`` compression requires the ``zlib``
standard library extension to be present.

The server support for various compressors is as follows:

- ``zstd`` requires and is enabled by default in MongoDB 4.2 or higher.
- ``snappy`` requires MongoDB 3.4 or higher and is enabled by default in
  MongoDB 3.6 or higher.
- ``zlib`` requires MongoDB 3.6 or higher and is enabled by default in
  MongoDB 4.2 and higher.


.. _server-api-parameters:

Server API Parameters
=====================

Starting with MongoDB 5.0, applications can request that the server behaves
in accordance with a particular server API version.

Server API parameters can be specified via the ``:server_api`` option to
``Client``. These parameters cannot be provided via a URI.

Currently the only defined API version is ``"1"``. It can be requested
as follows:

.. code-block:: ruby

  client = Mongo::Client.new(['localhost'], server_api: {version: "1"})

MongoDB server defines API versions as string values. For convenience, if the
API version is provided as an integer, the Ruby driver will stringify it and
send it to the server as a string:

.. code-block:: ruby

  client = Mongo::Client.new(['localhost'], server_api: {version: 1})

Note that the server may define API versions that are not stringified integers.
Applications must not assume that all legal API versions can be expressed
as integers.

When a particular API version is requested, operations which are part of that
API version behave as specified in that API version. Operations which are not
part of the specified API version behave as they would had the API version
not been specified at all. Operations whose behavior is subject to the
configured API version are commands including command arguments, queries,
aggregation pipeline stages and arguments.

Applications may request that the server rejects all operations which are not
part of the specified API version by setting the ``:strict`` option:

.. code-block:: ruby

  client = Mongo::Client.new(['localhost'], server_api: {version: "1", strict: true})

For example, since the ``:tailable`` option is not part of the server API
version 1, the following query would fail:

.. code-block:: ruby

  client = Mongo::Client.new(['localhost'], server_api: {version: "1", strict: true})
  client['collection'].find({}, tailable: true)
  # => Mongo::Error::OperationFailure (BSON field 'FindCommand.tailable' is not allowed with apiStrict:true. (323) (on localhost:27017, modern retry, attempt 1))

Applications may request that the server rejects all operations which are
deprecated in the specified API version by setting the ``:deprecation_errors``
option:

.. code-block:: ruby

  client = Mongo::Client.new(['localhost'], server_api: {version: "1", deprecation_errors: true})

Note that, as of this writing, there are no deprecated operations in API
version ``"1"``.

If the server API parameters have been defined on a ``Client`` object,
they will be sent by the client as part of each [*]_ executed operation.

.. [*] ``getMore`` commands and commands in transactions do not accept
   API parameters, thus the driver will not send them in these cases.

MongoDB servers prior to 5.0 do not recognize the API parameters, and will
produce a variety of errors should the application configure them.
The Ruby driver will send the API parameters to all MongoDB 3.6 and newer
servers, but the API parameters should only be configured when the application
is communicating with MongoDB 5.0 or newer servers. The API parameters
cannot be sent to MongoDB 3.4 and older servers that use the legacy wire
protocol; if an application configures the API parameters and connects to
MongoDB 3.4 or older servers, the driver will produce an error on every
operation.

The :ref:`command helper <arbitrary-commands>` permits the application to
send manually constructed commands to the server. If the client is not
configured with server API parameters, the command helper may be used to
issue commands with API parameters:

.. code-block:: ruby

  client.database.command(
    ping: 1,
    apiVersion: "1",
    apiStrict: false,
    apiDeprecationErrors: false,
  )

If the client is configured with server API parameters, the command helper
may not be used to issue commands with server API parameters. This includes the
case when the server API parameters provided to the client and to the
command helper are identical. If a client is constructed with server API
parameters, to send different API parameters (or none at all) a new client
must be constructed, either from scratch or using the ``with`` method.

The server API parameters may only be specified on the client level.
They may not be specified on the database, collection, session, transaction
or individual operation level.


Development Configuration
=========================

Driver's default configuration is suitable for production deployment.
In development, some settings can be adjusted to provide a better developer
experience.

- ``:server_selection_timeout``: set this to a low value (e.g., ``1``)
  if your MongoDB server is running locally and you start it manually. A low
  server selection timeout will cause the driver to fail quickly when there is
  no server running.


Production Configuration
========================

Please consider the following when deploying an application using the Ruby
driver in production:

- As of driver version 2.11, the ``:min_pool_size`` client option is completely
  respected - the driver will create that many connections to each server
  identified as a standalone, primary or secondary. In previous driver versions
  the driver created connections on demand. Applications using ``:min_pool_size``
  will see an increase in the number of idle connections to all servers as of
  driver version 2.11, and especially to secondaries in replica set deployments
  and to nodes in sharded clusters.
- If the application is reverse proxied to by another web server or a load
  balancer, ``server_selection_timeout`` should generally be set to a lower
  value than the reverse proxy's read timeout. For exampe, `Heroku request timeout
  <https://devcenter.heroku.com/articles/request-timeout>`_ is 30 seconds and
  is not configurable; if deploying a Ruby application using MongoDB to Heroku,
  consider lowering server selection timeout to 20 or 15 seconds.