Connection establishment during maintenance uses timeoutMS

XMLWordPrintableJSON

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • Java Drivers
    • None
    • None
    • None
    • None
    • None
    • None

      Per the connection monitoring spec:

      “Connections created as part of a connection pool’s minPoolSize maintenance routine MUST use connectTimeoutMS as the timeout for connection establishment… If timeoutMS is set, it MUST be used for subsequent handshake and authentication commands…”

      The driver currently applies timeoutMS for both connection establishment and subsequent handshake/authentication commands during minPoolSize maintenance, violating the spec. connectTimeoutMS should be used for socket connection, while timeoutMS (if set) is for handshakes only.

      This issue is only reproducible through debugging or using the custom test below, created during investigation (not part of the main codebase).

      /**
       * Not a prose spec test. However, it is additional test case for better coverage.
       * <p>
       * From the spec:
       * - When doing `minPoolSize` maintenance, `connectTimeoutMS` is used as the timeout for socket establishment.
       */
      @Test
      public void shouldUseConnectTimeoutMSWhenEstablishingConnectionInBackground() {
          assumeTrue(serverVersionAtLeast(4, 4));
      
          collectionHelper.runAdminCommand("{"
                  + "  configureFailPoint: \"failCommand\","
                  + "    mode: \"alwaysOn\","
                  + "  data: {"
                  + "    failCommands: [\"hello\", \"isMaster\"],"
                  + "    blockConnection: true,"
                  + "    blockTimeMS: " + 500
                  + "  }"
                  + "}");
      
          try (MongoClient mongoClient = createMongoClient(getMongoClientSettingsBuilder()
                  .applyToConnectionPoolSettings(builder -> builder.minSize(1))
                  // Use a very short timeout to ensure that the connection establishment will fail on the first handshake command.
                  .timeout(1, TimeUnit.MILLISECONDS))) {
              InternalStreamConnection.setRecordEverything(true);
      
              // Wait for the connection to start establishment in the background
              sleep(1000);
          }
          List<CommandStartedEvent> commandStartedEvents = commandListener.getCommandStartedEvents("isMaster");
          assertEquals(1, commandStartedEvents.size());
      
          List<CommandFailedEvent> commandFailedEvents = commandListener.getCommandFailedEvents("isMaster");
          assertEquals(1, commandFailedEvents.size());
          assertInstanceOf(MongoOperationTimeoutException.class, commandFailedEvents.get(0).getThrowable());
      } 

      Acceptance Criteria:

      • Ensure getConnectTimeout() in SocketStreamHelper or equivalent respects maintenance context and returns connectTimeoutMS not based on timeoutMS.
      • Consider removing usage of getReadTimeoutMS() in StreamSocket initialization if verified redundant, since setSoTimeout() is already applied before each read.
        • If not redundant, guard setSoTimeout() in socket initialization methods with a check for isMaintenanceContext to prevent premature MongoOperationTimeoutException.
      • Verify that handshake command timeouts during maintenance continue to respect timeoutMS (consider adding the test from the description).

              Assignee:
              Slav Babanin
              Reporter:
              Slav Babanin
              None
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated: