ExportXMLWordPrintableJSON

    • None
    • Java Drivers
    • None
    • None
    • None
    • None
    • None
    • None

      Spec requirements

      The Server Selection spec classifies listCollections as "should-use-primary": helpers "MUST use a read preference mode of 'primary', MUST NOT take a read preference argument and MUST ignore any default read preference from client, database or collection configuration".

      The Enumerate Databases spec carries an equivalent requirement for listDatabases: "Drivers MUST run the listDatabases command only on the primary node in replica set topology".

      No specification explicitly covers listIndexes in relation to read preference, but the behavior is implied in the server-selection spec to be equivalent to listCollections.

      Behavior

      The sync driver ignores the configured read preference for these commands and always selects the primary. The reactive streams driver honors it: with a secondary read preference on the client or database, it selects a secondary and sends the read preference in the command.

      Verified against a two-node replica set (primary on 27017, secondary on 27018), observing the listCollections commandStartedEvent:

      SYNC     listCollections -> server=localhost:27017 $readPreference=null
      REACTIVE listCollections -> server=localhost:27018 $readPreference={"mode": "secondary"}
      

      (same result for all three operations in both variants)

      Reproducer

      Against a replica set with at least one secondary:

      
      public class Reproducer {
          public static void main(final String[] args) throws Exception {
              CountDownLatch latch = new CountDownLatch(1);
              MongoClientSettings settings = MongoClientSettings.builder()
                      .applyConnectionString(new ConnectionString("mongodb://localhost:27017,localhost:27018/?replicaSet=rs0"))
                      .readPreference(ReadPreference.secondary())
                      .addCommandListener(new CommandListener() {
                          @Override
                          public void commandStarted(final CommandStartedEvent event) {
                              if (event.getCommandName().equals("listCollections")) {
                                  System.out.println(event.getConnectionDescription().getServerAddress()
                                          + " $readPreference=" + event.getCommand().get("$readPreference"));
                              }
                          }
                      })
                      .build();
      
              try (MongoClient client = MongoClients.create(settings)) {
                  client.getDatabase("admin").listCollections().subscribe(new Subscriber<BsonDocument>() {
                      @Override
                      public void onSubscribe(final Subscription s) {
                          s.request(Long.MAX_VALUE);
                      }
      
                      @Override
                      public void onNext(final BsonDocument t) {
                      }
      
                      @Override
                      public void onError(final Throwable t) {
                          t.printStackTrace();
                          latch.countDown();
                      }
      
                      @Override
                      public void onComplete() {
                          latch.countDown();
                      }
                  });
                  latch.await();
              }
          }
      }
      

      Output with the reactive streams client (swap in com.mongodb.client.MongoClients for the sync comparison):

      localhost:27018 $readPreference={"mode": "secondary"}
      

      Specification and test coverage

      There are currently no specification-defined tests of this requirement. The server-selection JSON tests only exercise the selection algorithm, and no unified test file combines a list* operation with a read preference assertion. Nothing driver-local covers it either.

      A unified-format regression test is feasible without format changes: assert that $readPreference does not exist on the listCollections commandStartedEvent when the entity is configured with secondary. There is precedent in run-command/tests/unified/runCommand.yml, which asserts exactly this for runCommand.

      Related

      • DRIVERS-1186 proposes relaxing the spec so these commands respect read preference. If that change is adopted, the fix direction reverses (the sync driver should stop forcing primary instead). This ticket tracks compliance with the current spec.

            Assignee:
            Unassigned
            Reporter:
            Jeffrey Yemin
            None
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: