Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-991

Cannot determine actual ReplSetStatus from singleton MongoClient getReplicaSetStatus()

    • Type: Icon: Improvement Improvement
    • Resolution: Won't Fix
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: API
    • Labels:
      None

      Our application is such that the majority of it can work whenever the Mongo ReplicaSet is operating without a PRIMARY. Recently I had a requirement to produce a HealthCheck service that reported the following states based upon the availability and capability of the Mongo ReplicaSet

      ReadWrite: ReplSet is operating with a PRIMARY, GET services should 20x, PUT services should 20x
      ReadOnly: ReplSet is operating with only SECONDARIES, GET services should 20x, PUT services should 503
      DOWN: No members of the ReplSet can be reached, services should 503

      I was surprised at how difficult it was to write this code with the 2.11.3 Java driver. The sticking point was that my application follows the http://docs.mongodb.org/ecosystem/tutorial/getting-started-with-java-driver/ convention of establishing a Singleton MongoClient. The ReplicaStatus object produced by this singleton provides no methods to assert the health of anything but the master (its toString(), however, does know this). This made it impossible to discriminate between ReadOnly and DOWN. I need the ReplicaSetStatus produced by the Singleton MongoClient to provide a direct way to interrogate the 3 states of the ReplSet as seen by the Application Server

      {ReadWrite, ReadOnly, DOWN}

      Here is my current ugly workaround. I am looking for a way to drive out the whole "freshClient" part.

      @Override
      public ReplSetStatus getReplSetStatus() {
      ReplSetStatus rss = ReplSetStatus.DOWN;
      MongoClient freshClient = null;
      try {
      if ( mongo != null ) {
      ReplicaSetStatus replicaSetStatus = mongo.getReplicaSetStatus();
      if ( replicaSetStatus != null ) {
      if ( replicaSetStatus.getMaster() != null )

      { rss = ReplSetStatus.ReadWrite; }

      else {
      /*

      • When mongo.getReplicaSetStatus().getMaster() returns null, it takes a a
      • fresh client to assert whether the ReplSet is read-only or completely
      • down. What a hack.
        */
        freshClient = new MongoClient( mongo.getAllAddress(), mongo.getMongoClientOptions() );
        replicaSetStatus = freshClient.getReplicaSetStatus();
        if ( replicaSetStatus != null ) { rss = replicaSetStatus.getMaster() != null ? ReplSetStatus.ReadWrite : ReplSetStatus.ReadOnly; }

        else

        { log.warn( "freshClient.getReplicaSetStatus() is null" ); }

        }
        } else

        { log.warn( "mongo.getReplicaSetStatus() returned null" ); }

        } else

        { throw new IllegalStateException( "mongo is null?!?" ); }

        } catch ( Throwable t )

        { log.error( "Ingore unexpected error", t ); }

        finally

        Unknown macro: { if ( freshClient != null ) { freshClient.close(); } }

        log.debug( "getReplSetStatus(): {}", rss );
        return rss;
        }

      Alternatively, if I could as the MongoClient "can you support this ReadPreference right now?" or "can you support this WriteConcern currently?" that would work too, or maybe even better.

      /**

      • @return true if current state of Client can support readPreference, false otherwise
        */
        boolean canDoRead( ReadPreference readPreference );

      /**

      • @return true if current state of Client can support writeConcern; false otherwise
        */
        boolean mongo.canDoWrite( WriteConcern writeConcern )

            Assignee:
            Unassigned Unassigned
            Reporter:
            bob_kuhar Bob Kuhar
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: