Why does the java driver ignore ReadPreference in certain instances?

576 views
Skip to first unread message

Alexander Mann

unread,
Jan 6, 2016, 3:52:36 PM1/6/16
to mongodb-user
I've been digging around in the Mongo Driver code recently and came across an interesting (I'm assuming) design decision.

In instances like `MongoClient.listDatabaseNames`, `MongoDatabase.listCollectionNames`, or `MongoCollection.listIndexes` they all ignore whatever read preference has been set, and instead use:

public <TResult> ListIndexesIterable<TResult> listIndexes(final Class<TResult> resultClass) {
return new ListIndexesIterableImpl<TResult>(getNamespace(), resultClass, codecRegistry, ReadPreference.primary(), executor);
}

My question is: Why not inherit the read-preference? Is this a performance thing? Are there known issues trying to read this type of information from secondaries?

This is causing (as far as I can tell) a bit of an issue for me, as I only have access to a secondary instance and am prone to seeing this (mind you I'm using the deprecated getDatabaseNames here):

Caused by: com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting for a server that matches ReadPreferenceServerSelector{readPreference=primary}. Client view of cluster state is {type=UNKNOWN, servers=[{address=10.0.6.244:32880, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message}, caused by {java.net.SocketTimeoutException: Read timed out}}]
at com.mongodb.connection.BaseCluster.createTimeoutException(BaseCluster.java:370)
at com.mongodb.connection.BaseCluster.selectServer(BaseCluster.java:101)
at com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.<init>(ClusterBinding.java:75)
at com.mongodb.binding.ClusterBinding$ClusterBindingConnectionSource.<init>(ClusterBinding.java:71)
at com.mongodb.binding.ClusterBinding.getReadConnectionSource(ClusterBinding.java:63)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:166)
at com.mongodb.operation.ListDatabasesOperation.execute(ListDatabasesOperation.java:100)
at com.mongodb.operation.ListDatabasesOperation.execute(ListDatabasesOperation.java:52)
at com.mongodb.Mongo.execute(Mongo.java:738)
at com.mongodb.Mongo$2.execute(Mongo.java:725)
at com.mongodb.OperationIterable.iterator(OperationIterable.java:47)
at com.mongodb.OperationIterable.forEach(OperationIterable.java:66)
at com.mongodb.MappingIterable.forEach(MappingIterable.java:50)
at com.mongodb.MappingIterable.into(MappingIterable.java:60)
at com.mongodb.Mongo.getDatabaseNames(Mongo.java:420)

Thanks for the time! 

Jeff Yemin

unread,
Jan 6, 2016, 6:06:47 PM1/6/16
to mongodb-user
Hi Alexander,

This is a design decision made as part of our server selection specification.  See this section in particular.

However, I may have a workaround for you.  If you construct your MongoClient instance with a single ServerAddress instead of a List<ServerAddress>, it will work as you expect.  That corresponds to the line in that section of the specification which reads:

Clients MUST NOT raise an exception if the topology type is Single

There was actually a bug in the 3.0.0 version of the driver with regard to this behavior, so please use 3.0.1 at a minimum.


Regards,
Jeff

Alexander Mann

unread,
Jan 7, 2016, 1:32:47 PM1/7/16
to mongodb-user
Brilliant reply. Thanks Jeff! I had not seen that doc on server selection, but from prior experience with Mongo had a sneaking suspicion about the standalone stuff. I tried that and got a new error message yesterday but was still curious about the above.

Thanks much!
Reply all
Reply to author
Forward
0 new messages