Skip to content

Commit 4a6008a

Browse files
MONGOID-5758: Add Mongoid.reconnect_clients and improve forking webserver documentation (#5808)
* This PR does the following: - Add Mongoid.reconnect_clients (analogous to Mongoid.disconnect_clients). The reason for adding this is to simply web server hooks (see added docs.) - Corrects the @return in the docs for disconnect_clients. Also added specs for the existing behavior. - Updates documentation related to web server forking. * Fix method name * More terse syntax * Preserve old return type * Update configuration.txt * Update configuration.txt
1 parent b29a402 commit 4a6008a

File tree

1 file changed

+48
-61
lines changed

1 file changed

+48
-61
lines changed

source/reference/configuration.txt

Lines changed: 48 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -863,58 +863,57 @@ as the following example shows:
863863
Usage with Forking Servers
864864
==========================
865865

866-
When using Mongoid with a forking web server such as Puma, Unicorn or
867-
Passenger, it is recommended to not perform any operations on Mongoid models
868-
in the parent process prior to the fork.
869-
870-
When a process forks, Ruby threads are not transferred to the child processes
871-
and the Ruby driver Client objects lose their background monitoring. The
872-
application will typically seem to work just fine until the deployment
873-
state changes (for example due to network errors, a maintenance event) at
874-
which point the application is likely to start getting ``NoServerAvailable``
875-
exception when performing MongoDB operations.
876-
877-
If the parent process needs to perform operations on the MongoDB database,
878-
reset all clients in the workers after they forked. How to do so depends
879-
on the web server being used.
880-
881-
If the parent process does not need to perform operations on the MongoDB
882-
database after child processes are forked, close the clients in the parent
883-
prior to forking children. If the parent process performs operations on a Mongo
884-
client and does not close it, the parent process will continue consuming a
885-
connection slot in the cluster and will continue monitoring the cluster for
886-
as long as the parent remains alive.
887-
888-
.. note::
889-
890-
The close/reconnect pattern described here should be used with Ruby driver
891-
version 2.6.2 or higher. Previous driver versions did not recreate
892-
monitoring threads when reconnecting.
866+
When using Mongoid with a forking web server such as Puma, or any application
867+
that otherwise forks to spawn child processes, special considerations apply.
868+
869+
If possible, we recommend to not perform any MongoDB operations in the parent
870+
process prior to forking, which will avoid any forking-related pitfalls.
871+
872+
A detailed technical explanation of how the Mongo Ruby Driver handles forking
873+
is given in the `driver's "Usage with Forking Servers" documentation
874+
<https://www.mongodb.com/docs/ruby-driver/current/reference/create-client/#usage-with-forking-servers>`.
875+
In a nutshell, to avoid various connection errors such as ``Mongo::Error::SocketError``
876+
and ``Mongo::Error::NoServerAvailable``, you must do the following:
877+
878+
1. Disconnect MongoDB clients in the parent Ruby process immediately *before*
879+
forking using ``Mongoid.disconnect_clients``. This ensures the parent and child
880+
process do not accidentally reuse the same sockets and have I/O conflicts.
881+
Note that ``Mongoid.disconnect_clients`` does not disrupt any in-flight
882+
MongoDB operations, and will automatically reconnect when you perform new
883+
operations.
884+
2. Reconnect your MongoDB clients in the child Ruby process immediately *after*
885+
forking using ``Mongoid.reconnect_clients``. This is required to respawn
886+
the driver's monitoring threads in the child process.
887+
888+
Most web servers provide hooks that can be used by applications to
889+
perform actions when the worker processes are forked. The following
890+
are configuration examples for several common Ruby web servers.
893891

894892
Puma
895893
----
896894

897895
Use the ``on_worker_boot`` hook to reconnect clients in the workers and
898-
the ``before_fork`` hook to close clients in the parent process
899-
(`Puma documentation <https://puma.io/puma/>`_):
896+
the ``before_fork`` and ``on_refork`` hooks to close clients in the
897+
parent process (`Puma documentation <https://puma.io/puma/#clustered-mode>`_).
900898

901899
.. code-block:: ruby
902900

903-
on_worker_boot do
904-
if defined?(Mongoid)
905-
Mongoid::Clients.clients.each do |name, client|
906-
client.close
907-
client.reconnect
908-
end
909-
else
910-
raise "Mongoid is not loaded. You may have forgotten to enable app preloading."
911-
end
912-
end
901+
# config/puma.rb
913902

903+
# Runs in the Puma master process before it forks a child worker.
914904
before_fork do
915-
if defined?(Mongoid)
916-
Mongoid.disconnect_clients
917-
end
905+
Mongoid.disconnect_clients
906+
end
907+
908+
# Required when using Puma's fork_worker option. Runs in the
909+
# child worker 0 process before it forks grandchild workers.
910+
on_refork do
911+
Mongoid.disconnect_clients
912+
end
913+
914+
# Runs in each Puma child process after it forks from its parent.
915+
on_worker_boot do
916+
Mongoid.reconnect_clients
918917
end
919918

920919
Unicorn
@@ -926,21 +925,14 @@ the ``before_fork`` hook to close clients in the parent process
926925

927926
.. code-block:: ruby
928927

929-
after_fork do |server, worker|
930-
if defined?(Mongoid)
931-
Mongoid::Clients.clients.each do |name, client|
932-
client.close
933-
client.reconnect
934-
end
935-
else
936-
raise "Mongoid is not loaded. You may have forgotten to enable app preloading."
937-
end
928+
# config/unicorn.rb
929+
930+
before_fork do |_server, _worker|
931+
Mongoid.disconnect_clients
938932
end
939933

940-
before_fork do |server, worker|
941-
if defined?(Mongoid)
942-
Mongoid.disconnect_clients
943-
end
934+
after_fork do |_server, _worker|
935+
Mongoid.reconnect_clients
944936
end
945937

946938
Passenger
@@ -956,12 +948,7 @@ before the workers are forked.
956948

957949
if defined?(PhusionPassenger)
958950
PhusionPassenger.on_event(:starting_worker_process) do |forked|
959-
if forked
960-
Mongoid::Clients.clients.each do |name, client|
961-
client.close
962-
client.reconnect
963-
end
964-
end
951+
Mongoid.reconnect_clients if forked
965952
end
966953
end
967954

0 commit comments

Comments
 (0)