/* * Tests that mongos does not mark nodes as down when reads or pings fail. */ (function() { 'use strict'; load("jstests/libs/fail_point_util.js"); load("jstests/replsets/rslib.js"); /* * Configures failCommand to force the given command to fail with the given error code when run * on the given namespace, and returns the resulting fail point. */ function configureFailCommand(nodeConn, command, ns, error) { return configureFailPoint( nodeConn, "failCommand", {failInternalCommands: true, errorCode: error, failCommands: [command], namespace: ns}); } const st = new ShardingTest({shards: 1, rs: {nodes: [{}, {rsConfig: {priority: 0}}]}}); const kDbName = "foo"; const kCollName = "bar"; const kNs = kDbName + "." + kCollName; const kErrorCode = ErrorCodes.HostUnreachable; const kPingWaitTimeMS = 12 * 1000; // streamable ReplicaSetMonitor's ping interval is 10 seconds. const testDB = st.s.getDB(kDbName); assert.commandWorked(st.s.adminCommand({enableSharding: kDbName})); assert.commandWorked(st.s.adminCommand({shardCollection: kNs, key: {x: 1}})); jsTest.log("Test that mongos does not mark the primary node as down when reads fail"); (() => { const cmdObj = { count: kCollName, query: {x: {$gte: 0}}, $readPreference: {mode: "primary"}, }; // Make the command fail on the primary node with HostUnreachable. const failPoint = configureFailCommand(st.rs0.nodes[0], "count", kNs, kErrorCode); assert.commandFailedWithCode(testDB.runCommand(cmdObj), kErrorCode); failPoint.off(); // Verify that the node was not marked as down (i.e. it is still the primary node and the // command with readPreference "primary" works). awaitRSClientHosts(st.s, st.rs0.nodes[0], {ok: true, ismaster: true}); assert.commandWorked(testDB.runCommand(cmdObj)); })(); jsTest.log("Test that mongos does not mark the secondary node as down when reads fail"); (() => { const cmdObj = { count: kCollName, query: {x: {$gte: 0}}, $readPreference: {mode: "secondary"}, }; // Make the command fail on the secondary node. const failPoint = configureFailCommand(st.rs0.nodes[1], "count", kNs, kErrorCode); assert.commandFailedWithCode(testDB.runCommand(cmdObj), kErrorCode); failPoint.off(); // Verify that the node was not marked as down (i.e. it is still the secondary node and the // command with readPreference "secondary" works). awaitRSClientHosts(st.s, st.rs0.nodes[1], {ok: true, secondary: true}); assert.commandWorked(testDB.runCommand(cmdObj)); })(); jsTest.log("Test that mongos does not mark the primary node as down when pings fail"); (() => { // Make ping commands fail on the primary node with HostUnreachable. Sleep for some // time to allow the ServerPingMonitor to send out pings. const failPoint = configureFailPoint( st.s, "serverPingMonitorFailWithHostUnreachable", {hostAndPort: st.rs0.nodes[0].host}); sleep(kPingWaitTimeMS); // Verify that the node was not marked as down (i.e. it is still the primary node and // we can run commands with readPreference "primary"). awaitRSClientHosts(st.s, st.rs0.nodes[0], {ok: true, ismaster: true}); const cmdObj = { count: kCollName, query: {x: {$gte: 0}}, $readPreference: {mode: "primary"}, }; assert.commandWorked(testDB.runCommand(cmdObj)); failPoint.off(); })(); jsTest.log("Test that mongos does not mark the secondary node as down when pings fail"); (() => { // Make ping commands fail on the secondary node with HostUnreachable. Sleep for some // time to allow the ServerPingMonitor to send out pings. const failPoint = configureFailPoint( st.s, "serverPingMonitorFailWithHostUnreachable", {hostAndPort: st.rs0.nodes[1].host}); sleep(kPingWaitTimeMS); // Verify that the node was not marked as down (i.e. it is still the secondary node and // we can run commands with readPreference "secondary"). awaitRSClientHosts(st.s, st.rs0.nodes[1], {ok: true, secondary: true}); const cmdObj = { count: kCollName, query: {x: {$gte: 0}}, $readPreference: {mode: "secondary"}, }; assert.commandWorked(testDB.runCommand(cmdObj)); failPoint.off(); })(); st.stop(); })();