My My Python web application has several connections registered on the same MongoDb server, but 3 different databases. The application is run by 4 Gunicorn employees.
I use a set of replicas.
When the primary object does not work, the current request fails, and an update is scheduled in MongoReplicaSetClient (2.8, but I think in 3.2 it is the same). The following request can be successful if, by the time, a new primary element is selected, and MonitorThread receives information about this by updating the connection with the client.
But the update only affects this client. Other clients connected to the same MongoDB server were not affected - the same story happens to everyone. This means that if each employee is connected to 3 databases on the same MongoDB server, and I repeat the same HTTP request that all 3 databases use, when the primary failure is not required, it takes unlimited time to update all connected clients. If each HTTP request goes through cyclically for each of 4 workers, we need 12 requests to update each Mongo client. But in fact, the requests are not bypassed.
A look into the PyMongo code MongoReplicaSetClient._send_message_with_response I see that when the primary file is turned off, self.disconnect is self.disconnect , which calls self.__schedule_refresh . This method has a sync argument, which allows you to "block until the update is complete."
My idea is to catch an AutoReconnect exception and call __schedule_refresh(sync=True) for all clients that are connected to the failed primary and block until a new replica set configuration is established. Thus, HTTP requests will not be processed (resulting in 500) until the database is normal.
But __schedule_refresh is a private method. In addition, I do not know if it will be called quickly on all clients - it looks like MonitorThread does its work at intervals.
Or maybe I could use MongoReplicaSetClient.refresh .
What do you think of this idea? Are there any disadvantages?
Will you help me with the implementation?