DEV Community

ScaleGrid for ScaleGrid

Posted on • Updated on • Originally published at scalegrid.io

MongoDB Ruby Driver 2.5.x Case-Sensitivity Issues with Hostnames on Replica Sets

ScaleGrid Blog: MongoDB Ruby Driver 2.5.x Case-Sensitivity Issues with Hostnames on Replica Sets

Having trouble connecting to MongoDB replica sets after upgrading the MongoDB Ruby driver to 2.5.x? We've recently received a few inquiries about this issue with the latest MongoDB Ruby driver version and wrote this post to share our findings on the problem and cause.

The error message that was encountered on connection attempt was -

No server is available matching preference: #<Mongo::ServerSelector::Primary:...>

The issue had been already reported to MongoDB and is being tracked here. We spent some time to investigate this issue and the root cause introduced in the driver code in 2.5.x.

MongoDB Ruby Driver 2.5.x Issue Summary

The issue exists in the 2.5.x version(s) of the MongoDB Ruby driver and is encountered when the hostnames comprising of the replica set contain case-sensitive characters, for example, ABC-server1.example.com. Possible workarounds are:

  1.  Downgrade to 2.4.x or upgrade 2.6.x once it's made available.
  2. Change the hostnames of all the members of the replica sets to downcase. For example, change the hostname in the example above to abc-server1.example.com.

Details On The Issue

Enabling detailed logging on Ruby provided a clue on what was happening:

...
#19140] DEBUG -- : MONGODB | Topology type 'replica set' initializing.
#19140] DEBUG -- : MONGODB | Server sg-connectiontest1-13622.servers.example.com:27017 initializing.
#19140] DEBUG -- : MONGODB | Server description for sg-connectiontest1-2.servers.example.com:27017 changed from 'unknown' to 'unknown'.
#19140] DEBUG -- : MONGODB | Server sg-connectiontest1-13623.servers.example.com:27017 initializing.
#19140] DEBUG -- : MONGODB | Server description for sg-connectiontest1-3.servers.example.com:27017 changed from 'unknown' to 'secondary'.
#19140] DEBUG -- : MONGODB | Server sg-connectiontest1-13624.servers.example.com:27017 initializing.
#19140] DEBUG -- : MONGODB | Server description for sg-connectiontest1-4.servers.example.com:27017 changed from 'unknown' to 'arbiter'.
#19140] DEBUG -- : MONGODB | There was a change in the members of the 'replica set' topology.
C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/mongo-2.5.1/lib/mongo/server_selector/selectable.rb:119:in `select_server': No server is available matching preference: # using server_selection_timeout=30 and local_threshold=0.015 (Mongo::Error::NoServerAvailable)
from lib/ruby/gems/2.4.0/gems/mongo-2.5.1/lib/mongo/database.rb:157:in `command'
from lib/ruby/gems/2.4.0/gems/mongo-2.5.1/lib/mongo/client.rb:404:in `list_databases'
from lib/ruby/gems/2.4.0/gems/mongo-2.5.1/lib/mongo/client.rb:385:in `database_names'
...

It seemed obvious that the driver was not able to detect the role of the primary of the replica set correctly. When comparing with the logs from 2.4.x, it was clear that this used to happen correctly on that version, i.e. the primary was correctly identified as the primary.

] DEBUG -- : MONGODB | Topology type 'replica set' initializing.
] DEBUG -- : MONGODB | Server sg-connectiontest1-13622.servers.example.com:27017 initializing.
] DEBUG -- : MONGODB | Server description for sg-connectiontest1-2.servers.example.com:27017 changed from 'unknown' to 'primary'.
] DEBUG -- : MONGODB | Server sg-connectiontest1-13623.servers.example.com:27017 initializing.
] DEBUG -- : MONGODB | Server description for sg-connectiontest1-3.servers.example.com:27017 changed from 'unknown' to 'secondary'.
] DEBUG -- : MONGODB | Server sg-connectiontest1-13624.servers.example.com:27017 initializing.
] DEBUG -- : MONGODB | Server description for sg-connectiontest1-4.servers.example.com:27017 changed from 'unknown' to 'arbiter'.

The other clue that we had was that our server names were slightly changed in the logs. Instead of the actual name SG-connectiontest1-2.servers.example.com, it was being logged as sg-connectiontest1-2.servers.example.com.

On inspecting the code around how hostnames are parsed during connection initialization and roles are assigned to them, we were able to determine that the driver code was down-casing (i.e. converting ABC.example.com to abc.example.com) while parsing the connection string. Next, the driver connects to the primary to discover the topology using the isMaster command. It's while parsing the result of this command, that the driver determines the role of each node.

However, while comparing hostnames returned from the command with the ones in the connection string, the driver was ignoring to perform a case-insensitive match. This led to a mismatch in names of the primary as reported by MongoDB to what the driver had determined from the connection string. This caused the role of the primary to become unknown and led to the connection failure. The address match check in the role detection code was added in 2.5.x.

The fix to the issue has been targeted to version 2.6.0 of the driver.

Top comments (0)