summaryrefslogtreecommitdiff
path: root/jstests/noPassthrough/auto_retry_on_network_error.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/noPassthrough/auto_retry_on_network_error.js')
-rw-r--r--jstests/noPassthrough/auto_retry_on_network_error.js213
1 files changed, 107 insertions, 106 deletions
diff --git a/jstests/noPassthrough/auto_retry_on_network_error.js b/jstests/noPassthrough/auto_retry_on_network_error.js
index 03e486a5a05..1c5f8465ebb 100644
--- a/jstests/noPassthrough/auto_retry_on_network_error.js
+++ b/jstests/noPassthrough/auto_retry_on_network_error.js
@@ -4,110 +4,111 @@
* @tags: [requires_replication]
*/
(function() {
- "use strict";
-
- load("jstests/libs/retryable_writes_util.js");
-
- if (!RetryableWritesUtil.storageEngineSupportsRetryableWrites(jsTest.options().storageEngine)) {
- jsTestLog("Retryable writes are not supported, skipping test");
- return;
- }
-
- TestData.networkErrorAndTxnOverrideConfig = {retryOnNetworkErrors: true};
- load('jstests/libs/override_methods/network_error_and_txn_override.js');
- load("jstests/replsets/rslib.js");
-
- function getThreadName(db) {
- let myUri = db.adminCommand({whatsmyuri: 1}).you;
- return db.getSiblingDB("admin")
- .aggregate([{$currentOp: {localOps: true}}, {$match: {client: myUri}}])
- .toArray()[0]
- .desc;
- }
-
- function failNextCommand(db, command) {
- let threadName = getThreadName(db);
-
- assert.commandWorked(db.adminCommand({
- configureFailPoint: "failCommand",
- mode: {times: 1},
- data: {
- closeConnection: true,
- failCommands: [command],
- threadName: threadName,
- }
- }));
- }
-
- const rst = new ReplSetTest({nodes: 1});
- rst.startSet();
-
- // awaitLastStableRecoveryTimestamp runs an 'appendOplogNote' command which is not retryable.
- rst.initiateWithAnyNodeAsPrimary(
- null, "replSetInitiate", {doNotWaitForStableRecoveryTimestamp: true});
-
- const dbName = "test";
- const collName = "auto_retry";
-
- // The override requires the connection to be run under a session. Use the replica set URL to
- // allow automatic re-targeting of the primary on NotMaster errors.
- const db = new Mongo(rst.getURL()).startSession({retryWrites: true}).getDatabase(dbName);
-
- // Commands with no disconnections should work as normal.
- assert.commandWorked(db.runCommand({ping: 1}));
- assert.commandWorked(db.runCommandWithMetadata({ping: 1}, {}).commandReply);
-
- // Read commands are automatically retried on network errors.
- failNextCommand(db, "find");
- assert.commandWorked(db.runCommand({find: collName}));
-
- failNextCommand(db, "find");
- assert.commandWorked(db.runCommandWithMetadata({find: collName}, {}).commandReply);
-
- // Retryable write commands that can be retried succeed.
- failNextCommand(db, "insert");
- assert.writeOK(db[collName].insert({x: 1}));
-
- failNextCommand(db, "insert");
- assert.commandWorked(db.runCommandWithMetadata({
- insert: collName,
- documents: [{x: 2}, {x: 3}],
- txnNumber: NumberLong(10),
- lsid: {id: UUID()}
- },
- {})
- .commandReply);
-
- // Retryable write commands that cannot be retried (i.e. no transaction number, no session id,
- // or are unordered) throw.
- failNextCommand(db, "insert");
- assert.throws(function() {
- db.runCommand({insert: collName, documents: [{x: 1}, {x: 2}], ordered: false});
- });
-
- // The previous command shouldn't have been retried, so run a command to successfully re-target
- // the primary, so the connection to it can be closed.
- assert.commandWorked(db.runCommandWithMetadata({ping: 1}, {}).commandReply);
-
- failNextCommand(db, "insert");
- assert.throws(function() {
- db.runCommandWithMetadata({insert: collName, documents: [{x: 1}, {x: 2}], ordered: false},
- {});
- });
-
- // getMore commands can't be retried because we won't know whether the cursor was advanced or
- // not.
- let cursorId = assert.commandWorked(db.runCommand({find: collName, batchSize: 0})).cursor.id;
- failNextCommand(db, "getMore");
- assert.throws(function() {
- db.runCommand({getMore: cursorId, collection: collName});
- });
-
- cursorId = assert.commandWorked(db.runCommand({find: collName, batchSize: 0})).cursor.id;
- failNextCommand(db, "getMore");
- assert.throws(function() {
- db.runCommandWithMetadata({getMore: cursorId, collection: collName}, {});
- });
-
- rst.stopSet();
+"use strict";
+
+load("jstests/libs/retryable_writes_util.js");
+
+if (!RetryableWritesUtil.storageEngineSupportsRetryableWrites(jsTest.options().storageEngine)) {
+ jsTestLog("Retryable writes are not supported, skipping test");
+ return;
+}
+
+TestData.networkErrorAndTxnOverrideConfig = {
+ retryOnNetworkErrors: true
+};
+load('jstests/libs/override_methods/network_error_and_txn_override.js');
+load("jstests/replsets/rslib.js");
+
+function getThreadName(db) {
+ let myUri = db.adminCommand({whatsmyuri: 1}).you;
+ return db.getSiblingDB("admin")
+ .aggregate([{$currentOp: {localOps: true}}, {$match: {client: myUri}}])
+ .toArray()[0]
+ .desc;
+}
+
+function failNextCommand(db, command) {
+ let threadName = getThreadName(db);
+
+ assert.commandWorked(db.adminCommand({
+ configureFailPoint: "failCommand",
+ mode: {times: 1},
+ data: {
+ closeConnection: true,
+ failCommands: [command],
+ threadName: threadName,
+ }
+ }));
+}
+
+const rst = new ReplSetTest({nodes: 1});
+rst.startSet();
+
+// awaitLastStableRecoveryTimestamp runs an 'appendOplogNote' command which is not retryable.
+rst.initiateWithAnyNodeAsPrimary(
+ null, "replSetInitiate", {doNotWaitForStableRecoveryTimestamp: true});
+
+const dbName = "test";
+const collName = "auto_retry";
+
+// The override requires the connection to be run under a session. Use the replica set URL to
+// allow automatic re-targeting of the primary on NotMaster errors.
+const db = new Mongo(rst.getURL()).startSession({retryWrites: true}).getDatabase(dbName);
+
+// Commands with no disconnections should work as normal.
+assert.commandWorked(db.runCommand({ping: 1}));
+assert.commandWorked(db.runCommandWithMetadata({ping: 1}, {}).commandReply);
+
+// Read commands are automatically retried on network errors.
+failNextCommand(db, "find");
+assert.commandWorked(db.runCommand({find: collName}));
+
+failNextCommand(db, "find");
+assert.commandWorked(db.runCommandWithMetadata({find: collName}, {}).commandReply);
+
+// Retryable write commands that can be retried succeed.
+failNextCommand(db, "insert");
+assert.writeOK(db[collName].insert({x: 1}));
+
+failNextCommand(db, "insert");
+assert.commandWorked(db.runCommandWithMetadata({
+ insert: collName,
+ documents: [{x: 2}, {x: 3}],
+ txnNumber: NumberLong(10),
+ lsid: {id: UUID()}
+ },
+ {})
+ .commandReply);
+
+// Retryable write commands that cannot be retried (i.e. no transaction number, no session id,
+// or are unordered) throw.
+failNextCommand(db, "insert");
+assert.throws(function() {
+ db.runCommand({insert: collName, documents: [{x: 1}, {x: 2}], ordered: false});
+});
+
+// The previous command shouldn't have been retried, so run a command to successfully re-target
+// the primary, so the connection to it can be closed.
+assert.commandWorked(db.runCommandWithMetadata({ping: 1}, {}).commandReply);
+
+failNextCommand(db, "insert");
+assert.throws(function() {
+ db.runCommandWithMetadata({insert: collName, documents: [{x: 1}, {x: 2}], ordered: false}, {});
+});
+
+// getMore commands can't be retried because we won't know whether the cursor was advanced or
+// not.
+let cursorId = assert.commandWorked(db.runCommand({find: collName, batchSize: 0})).cursor.id;
+failNextCommand(db, "getMore");
+assert.throws(function() {
+ db.runCommand({getMore: cursorId, collection: collName});
+});
+
+cursorId = assert.commandWorked(db.runCommand({find: collName, batchSize: 0})).cursor.id;
+failNextCommand(db, "getMore");
+assert.throws(function() {
+ db.runCommandWithMetadata({getMore: cursorId, collection: collName}, {});
+});
+
+rst.stopSet();
})();