How do you check if the client for a MongoDB instance is valid?
The serverSelectionTimeoutMS
keyword parameter of pymongo.mongo_client.MongoClient
controls how long the driver will try to connect to a server. The default value is 30s.
Set it to a very low value compatible with your typical connection time¹ to immediately report an error. You need to query the DB after that to trigger a connection attempt :
>>> maxSevSelDelay = 1 # Assume 1ms maximum server selection delay
>>> client = pymongo.MongoClient("someInvalidURIOrNonExistantHost",
serverSelectionTimeoutMS=maxSevSelDelay)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>> client.server_info()
This will raise pymongo.errors.ServerSelectionTimeoutError
.
¹ Apparently setting serverSelectionTimeoutMS
to 0
might even work in the particular case your server has very low latency (case of a "local" server with very light load for example)
It is up to you to catch that exception and to handle it properly. Something like that:
try:
client = pymongo.MongoClient("someInvalidURIOrNonExistantHost",
serverSelectionTimeoutMS=maxSevSelDelay)
client.server_info() # force connection on a request as the
# connect=True parameter of MongoClient seems
# to be useless here
except pymongo.errors.ServerSelectionTimeoutError as err:
# do whatever you need
print(err)
will display:
No servers found yet
serverSelectionTimeoutMS
doesn't work for me (Python 2.7.12, MongoDB 3.6.1, pymongo 3.6.0). A. Jesse Jiryu Davis suggested in a GitHub issue that we attempt a socket-level connection first as a litmus test. This does the trick for me.
def throw_if_mongodb_is_unavailable(host, port):
import socket
sock = None
try:
sock = socket.create_connection(
(host, port),
timeout=1) # one second
except socket.error as err:
raise EnvironmentError(
"Can't connect to MongoDB at {host}:{port} because: {err}"
.format(**locals()))
finally:
if sock is not None:
sock.close()
# elsewhere...
HOST = 'localhost'
PORT = 27017
throw_if_mongodb_is_unavailable(HOST, PORT)
import pymongo
conn = pymongo.MongoClient(HOST, PORT)
print(conn.admin.command('ismaster'))
# etc.
There are plenty of problems this won't catch, but if the server isn't running or isn't reachable, this'll show you right away.
serverSelectionTimeoutMS
This defines how long to block for server selection before throwing an exception. The default is 30,000 (milliseconds). It MUST be configurable at the client level. It MUST NOT be configurable at the level of a database object, collection object, or at the level of an individual query.
This default value was chosen to be sufficient for a typical server primary election to complete. As the server improves the speed of elections, this number may be revised downward.
Users that can tolerate long delays for server selection when the topology is in flux can set this higher. Users that want to "fail fast" when the topology is in flux can set this to a small number.
A serverSelectionTimeoutMS of zero MAY have special meaning in some drivers; zero's meaning is not defined in this spec, but all drivers SHOULD document the meaning of zero.
https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#serverselectiontimeoutms
# pymongo 3.5.1
from pymongo import MongoClient
from pymongo.errors import ServerSelectionTimeoutError
client = MongoClient("mongodb://localhost:27000/", serverSelectionTimeoutMS=10, connectTimeoutMS=20000)
try:
info = client.server_info() # Forces a call.
except ServerSelectionTimeoutError:
print("server is down.")
# If connection create a new one with serverSelectionTimeoutMS=30000
Hi to find out that the connection is established or not you can do that :
from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
client = MongoClient()
try:
# The ismaster command is cheap and does not require auth.
client.admin.command('ismaster')
except ConnectionFailure:
print("Server not available")