diff options
author | Luis Osta <luis.osta@mongodb.com> | 2020-07-15 15:10:09 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-08-12 04:57:57 +0000 |
commit | 290fc62c9574828bb2c176a794f311935b31e8d4 (patch) | |
tree | 53c1fa9389268bb45c7117c46cd710e6c4f5f348 | |
parent | 18e6827bd918c06b5d43d39b2f196102973ea31d (diff) | |
download | mongo-290fc62c9574828bb2c176a794f311935b31e8d4.tar.gz |
SERVER-49044 Make AsyncRequestSender not retry remote command requests with startTransaction=true
(cherry picked from commit e4ad46c0fab6ce2b633f212db65ab5479c4c191e)
-rw-r--r-- | jstests/sharding/mongos_not_retry_commands_in_transactions.js | 74 | ||||
-rw-r--r-- | src/mongo/s/async_requests_sender.cpp | 5 |
2 files changed, 76 insertions, 3 deletions
diff --git a/jstests/sharding/mongos_not_retry_commands_in_transactions.js b/jstests/sharding/mongos_not_retry_commands_in_transactions.js new file mode 100644 index 00000000000..44d6dcbf149 --- /dev/null +++ b/jstests/sharding/mongos_not_retry_commands_in_transactions.js @@ -0,0 +1,74 @@ +/* + * Tests that mongos doesn't retry commands with startTransaction=true. + * @tags: [requires_fcv_44] + */ +(function() { +'use strict'; + +const setCommandToFail = (nodeConnection, command, namespace) => { + return nodeConnection.adminCommand({ + configureFailPoint: 'failCommand', + mode: {times: 1}, + data: { + errorCode: ErrorCodes.InterruptedDueToReplStateChange, + failCommands: [command], + namespace, + failInternalCommands: true + } + }); +}; + +const kDbName = "testDb"; +const kCollName = "testColl"; +const kNs = `${kDbName}.${kCollName}`; + +const kDoc0 = { + _id: 0 +}; +const kDoc1 = { + _id: 1 +}; + +let transactionNumber = 1; + +const st = new ShardingTest({ + mongos: 1, + shards: 1, + rs: {nodes: 1}, +}); + +// Initializes test and inserts dummy document +jsTest.log("Inserting test document."); +const mongosDB = st.s0.startSession().getDatabase(kDbName); +const primaryConnection = st.rs0.getPrimary(); + +assert.commandWorked(mongosDB.runCommand({ + insert: kCollName, + documents: [kDoc0], +})); + +// Set the failCommand failpoint to make the next 'find' command fail once due to a failover. +// Start a transaction & execute a find command. +// It should fail once due to the 'failCommand' failpoint and should not be retried. +jsTest.log( + "Testing that mongos doesn't retry the read command with startTransaction=true on replication set failover."); +assert.commandWorked(setCommandToFail(primaryConnection, "find", kNs)); + +assert.commandFailedWithCode(mongosDB.runCommand({ + find: kCollName, + filter: kDoc0, + startTransaction: true, + txnNumber: NumberLong(transactionNumber++), + stmtId: NumberInt(0), + autocommit: false +}), + ErrorCodes.InterruptedDueToReplStateChange); + +jsTest.log("Testing that mongos retries retryable writes on failover."); +assert.commandWorked(setCommandToFail(primaryConnection, "insert", kNs)); + +assert.commandWorked(mongosDB.runCommand( + {insert: kCollName, documents: [kDoc1], txnNumber: NumberLong(transactionNumber++)})); + +st.stop(); +})();
\ No newline at end of file diff --git a/src/mongo/s/async_requests_sender.cpp b/src/mongo/s/async_requests_sender.cpp index 36f91459d29..7cca30f0b99 100644 --- a/src/mongo/s/async_requests_sender.cpp +++ b/src/mongo/s/async_requests_sender.cpp @@ -272,9 +272,9 @@ auto AsyncRequestsSender::RemoteData::handleResponse(RemoteCommandOnAnyCallbackA } shard->updateReplSetMonitor(failedTargets.front(), status); - + bool isStartingTransaction = _cmdObj.getField("startTransaction").booleanSafe(); if (!_ars->_stopRetrying && shard->isRetriableError(status.code(), _ars->_retryPolicy) && - _retryCount < kMaxNumFailedHostRetryAttempts) { + _retryCount < kMaxNumFailedHostRetryAttempts && !isStartingTransaction) { LOGV2_DEBUG(4615637, 1, @@ -284,7 +284,6 @@ auto AsyncRequestsSender::RemoteData::handleResponse(RemoteCommandOnAnyCallbackA "shardId"_attr = _shardId, "hosts"_attr = failedTargets, "error"_attr = redact(status)); - ++_retryCount; _shardHostAndPort.reset(); // retry through recursion |