@@ -1641,102 +1641,83 @@ Usage with Forking Servers
16411641
16421642.. note::
16431643
1644- Applications using Mongoid should follow `Mongoid's forking guidance
1645- <https://mongodb.com/docs/mongoid/current/tutorials/mongoid-configuration/#usage-with-forking-servers>`_.
1646- The guidance and sample code below is provided for applications using the
1647- Ruby driver directly.
1644+ Applications using Mongoid should follow `Mongoid's "Usage with Forking Servers" documentation
1645+ <https://www.mongodb.com/docs/mongoid/current/reference/configuration/#usage-with-forking-servers>`_.
1646+ The guidance below is provided for applications using the Ruby driver directly.
16481647
16491648When using the Mongo Ruby driver in a Web application with a forking web server
1650- such as Unicorn, Puma or Passenger, or when the application otherwise forks,
1651- each process should generally each have their own ``Mongo::Client`` instances.
1652- This is because:
1653-
1654- 1. The background threads remain in the parent process and are not transferred
1655- to the child process.
1656- 2. File descriptors like network sockets are shared between parent and
1657- child processes.
1658-
1659- The driver attempts to detect client use from forked processes and
1660- reestablish network connections when such use is detected, alleviating
1661- the issue of file descriptor sharing.
1662-
1663- If both parent and child processes need to perform MongoDB operations,
1664- it is recommended for each of the processes to create their own
1665- ``Mongo::Client`` instances. Specifically, the child process should create
1666- its own client instance and not use any of the instances that were created
1667- in the parent.
1668-
1669- If the parent continues to perform MongoDB operations using an already
1670- established client instance after forking children, this client instance will
1671- continue to operate normally as long as no child uses it in any way.
1672- The child processes will not inherit any of the monitoring threads, and
1673- will not perform background operations on the client instance.
1674-
1675- If the parent does not need to perform MongoDB operation after forking
1676- children (which is what typically happens in web applications), the parent
1677- should close all of the client instances it created to free up connections
1678- and cease background monitoring:
1649+ such as Puma, or when the application otherwise forks, each process (parent and child)
1650+ must have its own client connections. This is because:
1651+
1652+ 1. Background Ruby threads, such as those used by the Ruby MongoDB driver to
1653+ monitor connection state, are **not** transferred to the child process.
1654+ 2. File descriptors like network sockets **are** shared between parent and
1655+ child processes, which can cause I/O conflicts.
1656+
1657+ Regarding (1), if you do not restart the driver's monitoring threads
1658+ on the child process after forking, although your child may initially
1659+ appear to function correctly, you will eventually see
1660+ ``Mongo::Error::NoServerAvailable`` exceptions if/when your MongoDB cluster
1661+ state changes, for example due to network errors or a maintenance event.
1662+
1663+ Regarding (2), if a child process reuses the parent's file descriptors, you
1664+ will see ``Mongo::Error::SocketError`` errors with messages such as
1665+ ``Errno::EPIPE: Broken pipe`` and ``EOFError: end of file reached``.
1666+
1667+ When the Ruby driver is used in a web application, if possible,
1668+ we recommend to not create any ``Mongo::Client`` instances in the parent
1669+ process (prior to the workers being forked), and instead only create client
1670+ instances in the workers.
1671+
1672+ Manually Handling Process Forks
1673+ -------------------------------
1674+
1675+ Certain advanced use cases, such as `Puma's fork_worker option <https://github.com/puma/puma/blob/master/docs/fork_worker.md>`_,
1676+ require ``Mongo::Client`` instances to be open in both the parent
1677+ and child processes. In this case, you must handle client
1678+ reconnection manually.
1679+
1680+ To do this, immediately before forking, close any existing client connections
1681+ on your parent process. This will prevent the parent process from experiencing
1682+ network and monitoring errors due to the child's reuse of the parent's
1683+ file descriptors.
16791684
16801685.. code-block:: ruby
16811686
1682- client.reconnect
1687+ # Immediately before fork
1688+ client.close
16831689
16841690.. note::
16851691
1686- If the parent process performs operations on the Mongo client and does not
1687- close it, the parent process will continue consuming a connection slot
1688- in the cluster and will continue monitoring the cluster for as long as the
1689- parent remains alive.
1690-
1691- Reconnecting Client Instances
1692- -----------------------------
1692+ Calling ``Client#close`` does not disrupt database operations currently in-flight.
1693+ Clients will automatically reconnect when you perform new operations.
16931694
1694- When the Ruby driver is used in a web application, it is recommended to not
1695- create any ``Mongo::Client`` instances in the management processes (prior to
1696- the workers being forked), and instead only create client instances in the
1697- workers.
1698-
1699- It is possible, although not recommended, to use the same ``Mongo::Client``
1700- instances in parent and child processes. In order to do so, the instance
1701- must be closed and reconnected in the child process so that the background
1702- threads can be recreated:
1695+ Then, immediately after forking, reconnect your clients in the newly
1696+ forked child process, which will respawn the driver's monitoring threads.
17031697
17041698.. code-block:: ruby
17051699
1706- client.close
1700+ # Immediately after fork
17071701 client.reconnect
17081702
1709- .. note::
1710-
1711- This pattern should be used with Ruby driver version 2.6.2 or higher.
1712- Previous driver versions did not recreate monitoring threads when
1713- reconnecting.
1714-
1715- .. note::
1716-
1717- When closing and reconnecting the client instance in the child,
1718- due to file descriptor sharing, the parent process may experience network
1719- and monitoring errors.
1720-
1721- Web servers generally provide hooks that can be used by applications to
1722- perform actions when the worker processes are forked. The recommended hooks
1723- to use are:
1703+ Most web servers provide hooks that can be used by applications to
1704+ perform actions when the worker processes are forked. The recommended
1705+ hooks are:
17241706
1725- - For `Puma <https://puma.io/puma/>`_, ``before_fork`` to close clients in the
1726- parent process and ``on_worker_boot`` to reconnect in the child processes.
1707+ - For `Puma <https://puma.io/puma/#clustered-mode>`_,
1708+ use ``before_fork`` and ``on_refork`` to close clients in
1709+ the parent process and ``on_worker_boot`` to reconnect in the
1710+ child processes.
17271711- For `Unicorn <https://yhbt.net/unicorn/Unicorn/Configurator.html>`_,
17281712 ``before_fork`` to close clients in the parent process and
17291713 ``after_fork`` to reconnect clients in the child processes.
17301714- For `Passenger <https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/#unintentional-file-descriptor-sharing>`_,
17311715 ``starting_worker_process`` to reconnect clients in the child processes
17321716 (Passenger does not appear to have a pre-fork hook).
17331717
1734- This documentation does not provide example code for using the aforementioned
1735- hooks, because there is no standard for client instance management when
1736- using the Ruby driver directly. `Mongoid documentation
1737- <https://mongodb.com/docs/mongoid/current/tutorials/mongoid-configuration/#usage-with-forking-servers>`_
1738- however provides examples for closing clients in the parent process and
1739- reconnecting clients in the child processes.
1718+ Refer to `Mongoid's "Usage with Forking Servers" documentation
1719+ <https://www.mongodb.com/docs/mongoid/current/reference/configuration/#usage-with-forking-servers>`_
1720+ for further examples.
17401721
17411722Troubleshooting
17421723---------------
0 commit comments