diff options
-rw-r--r-- | jstests/libs/override_methods/implicitly_retry_on_database_drop_pending.js | 12 | ||||
-rw-r--r-- | jstests/libs/override_methods/inject_tenant_prefix.js | 27 | ||||
-rw-r--r-- | jstests/libs/override_methods/network_error_and_txn_override.js | 13 | ||||
-rw-r--r-- | jstests/libs/override_methods/override_helpers.js | 11 | ||||
-rw-r--r-- | jstests/libs/override_methods/retry_writes_at_least_once.js | 10 | ||||
-rw-r--r-- | jstests/noPassthrough/auto_retry_on_network_error.js | 22 | ||||
-rw-r--r-- | jstests/replsets/last_op_visible.js | 37 | ||||
-rw-r--r-- | jstests/replsets/read_committed_no_snapshots.js | 12 | ||||
-rw-r--r-- | jstests/replsets/read_committed_on_secondary.js | 14 | ||||
-rw-r--r-- | jstests/sharding/auth_sharding_cmd_metadata.js | 7 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/mongo.cpp | 18 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/mongo.h | 1 | ||||
-rw-r--r-- | src/mongo/shell/mongo.js | 4 | ||||
-rw-r--r-- | src/mongo/shell/session.js | 11 |
14 files changed, 50 insertions, 149 deletions
diff --git a/jstests/libs/override_methods/implicitly_retry_on_database_drop_pending.js b/jstests/libs/override_methods/implicitly_retry_on_database_drop_pending.js index f9a72ca1d5f..19da7af8ae8 100644 --- a/jstests/libs/override_methods/implicitly_retry_on_database_drop_pending.js +++ b/jstests/libs/override_methods/implicitly_retry_on_database_drop_pending.js @@ -8,7 +8,6 @@ const defaultTimeout = 10 * 60 * 1000; const mongoRunCommandOriginal = Mongo.prototype.runCommand; -const mongoRunCommandWithMetadataOriginal = Mongo.prototype.runCommandWithMetadata; function runCommandWithRetries(conn, dbName, commandObj, func, makeFuncArgs) { if (typeof commandObj !== "object" || commandObj === null) { @@ -18,8 +17,7 @@ function runCommandWithRetries(conn, dbName, commandObj, func, makeFuncArgs) { // We create a copy of 'commandObj' to avoid mutating the parameter the caller specified. // Instead, we use the makeFuncArgs() function to build the array of arguments to 'func' by // giving it the 'commandObj' that should be used. This is done to work around the - // difference in the order of parameters for the Mongo.prototype.runCommand() and - // Mongo.prototype.runCommandWithMetadata() functions. + // difference in the order of parameters for the Mongo.prototype.runCommand() function. commandObj = Object.assign({}, commandObj); const commandName = Object.keys(commandObj)[0]; let resPrevious; @@ -138,12 +136,4 @@ Mongo.prototype.runCommand = function(dbName, commandObj, options) { mongoRunCommandOriginal, (commandObj) => [dbName, commandObj, options]); }; - -Mongo.prototype.runCommandWithMetadata = function(dbName, metadata, commandArgs) { - return runCommandWithRetries(this, - dbName, - commandArgs, - mongoRunCommandWithMetadataOriginal, - (commandArgs) => [dbName, metadata, commandArgs]); -}; })(); diff --git a/jstests/libs/override_methods/inject_tenant_prefix.js b/jstests/libs/override_methods/inject_tenant_prefix.js index fc9a1f11952..cfd44378644 100644 --- a/jstests/libs/override_methods/inject_tenant_prefix.js +++ b/jstests/libs/override_methods/inject_tenant_prefix.js @@ -12,7 +12,6 @@ load("jstests/libs/transactions_util.js"); // Save references to the original methods in the IIFE's scope. // This scoping allows the original methods to be called by the overrides below. let originalRunCommand = Mongo.prototype.runCommand; -let originalRunCommandWithMetadata = Mongo.prototype.runCommandWithMetadata; const denylistedDbNames = ["config", "admin", "local"]; @@ -609,32 +608,6 @@ Mongo.prototype.runCommand = function(dbName, cmdObj, options) { return resObj; }; -Mongo.prototype.runCommandWithMetadata = function(dbName, metadata, cmdObj) { - const dbNameWithTenantId = prependTenantIdToDbNameIfApplicable(dbName); - - // Use cmdObj with TestData.tenantId prepended to all the applicable database names and - // namespaces. - const originalCmdObjContainsTenantId = isCmdObjWithTenantId(cmdObj); - let cmdObjWithTenantId = - originalCmdObjContainsTenantId ? cmdObj : createCmdObjWithTenantId(cmdObj); - - let resObj = this.runCommandRetryOnTenantMigrationErrors( - dbNameWithTenantId, - cmdObjWithTenantId, - () => originalRunCommandWithMetadata.apply( - this, [dbNameWithTenantId, metadata, cmdObjWithTenantId]), - () => this.reroutingMongo.runCommandWithMetadata( - dbNameWithTenantId, metadata, cmdObjWithTenantId)); - - if (!originalCmdObjContainsTenantId) { - // Remove TestData.tenantId from all database names and namespaces in the resObj since tests - // assume the command was run against the original database. - removeTenantId(resObj); - } - - return resObj; -}; - OverrideHelpers.prependOverrideInParallelShell( "jstests/libs/override_methods/inject_tenant_prefix.js"); }()); diff --git a/jstests/libs/override_methods/network_error_and_txn_override.js b/jstests/libs/override_methods/network_error_and_txn_override.js index 4877de151f1..4616ded0580 100644 --- a/jstests/libs/override_methods/network_error_and_txn_override.js +++ b/jstests/libs/override_methods/network_error_and_txn_override.js @@ -9,13 +9,12 @@ * retries transactions that fail due to implicit collection creation. * * (2) When a network connection to the mongo shell is closed, attempting to call - * Mongo.prototype.runCommand() and Mongo.prototype.runCommandWithMetadata() throws a JavaScript - * exception. This override catches these exceptions (i.e. ones where isNetworkError() returns true) - * and automatically re-sends the command request to the server, or propagates the error if the - * command should already be using the shell's existing retryability logic. The goal of this - * override is to implement retry logic such that the assertions within our existing JavaScript - * tests still pass despite stepdowns of replica set primaries (optionally in sharded clusters) - * happening in the background. + * Mongo.prototype.runCommand() throws a JavaScript exception. This override catches these + * exceptions (i.e. ones where isNetworkError() returns true) and automatically re-sends the + * command request to the server, or propagates the error if the command should already be using + * the shell's existing retryability logic. The goal of this override is to implement retry logic + * such that the assertions within our existing JavaScript tests still pass despite stepdowns of + * replica set primaries (optionally in sharded clusters) happening in the background. * * These two overrides are unified to simplify the retry logic. * diff --git a/jstests/libs/override_methods/override_helpers.js b/jstests/libs/override_methods/override_helpers.js index f4db0871bcf..143bc09d264 100644 --- a/jstests/libs/override_methods/override_helpers.js +++ b/jstests/libs/override_methods/override_helpers.js @@ -74,7 +74,6 @@ var OverrideHelpers = (function() { function overrideRunCommand(overrideFunc) { const mongoRunCommandOriginal = Mongo.prototype.runCommand; - const mongoRunCommandWithMetadataOriginal = Mongo.prototype.runCommandWithMetadata; Mongo.prototype.runCommand = function(dbName, commandObj, options) { const commandName = Object.keys(commandObj)[0]; @@ -85,16 +84,6 @@ var OverrideHelpers = (function() { mongoRunCommandOriginal, (commandObj) => [dbName, commandObj, options]); }; - - Mongo.prototype.runCommandWithMetadata = function(dbName, metadata, commandArgs) { - const commandName = Object.keys(commandArgs)[0]; - return overrideFunc(this, - dbName, - commandName, - commandArgs, - mongoRunCommandWithMetadataOriginal, - (commandArgs) => [dbName, metadata, commandArgs]); - }; } return { diff --git a/jstests/libs/override_methods/retry_writes_at_least_once.js b/jstests/libs/override_methods/retry_writes_at_least_once.js index cde81b5cc7f..ca5be2bbff0 100644 --- a/jstests/libs/override_methods/retry_writes_at_least_once.js +++ b/jstests/libs/override_methods/retry_writes_at_least_once.js @@ -1,7 +1,6 @@ /** - * Overrides Mongo.prototype.runCommand and Mongo.prototype.runCommandWithMetadata to retry all - * retryable writes at least once, randomly more than that, regardless of the outcome of the - * command. Returns the result of the latest attempt. + * Overrides Mongo.prototype.runCommand to retry all retryable writes at least once, randomly more + * than that, regardless of the outcome of the command. Returns the result of the latest attempt. */ (function() { "use strict"; @@ -14,16 +13,11 @@ Random.setRandomSeed(); const kExtraRetryProbability = 0.2; const mongoRunCommandOriginal = Mongo.prototype.runCommand; -const mongoRunCommandWithMetadataOriginal = Mongo.prototype.runCommandWithMetadata; Mongo.prototype.runCommand = function runCommand(dbName, cmdObj, options) { return runWithRetries(this, cmdObj, mongoRunCommandOriginal, arguments); }; -Mongo.prototype.runCommandWithMetadata = function runCommandWithMetadata(dbName, metadata, cmdObj) { - return runWithRetries(this, cmdObj, mongoRunCommandWithMetadataOriginal, arguments); -}; - function runWithRetries(mongo, cmdObj, clientFunction, clientFunctionArguments) { let cmdName = Object.keys(cmdObj)[0]; diff --git a/jstests/noPassthrough/auto_retry_on_network_error.js b/jstests/noPassthrough/auto_retry_on_network_error.js index 7b2e3a145cf..29e5e5b1a1c 100644 --- a/jstests/noPassthrough/auto_retry_on_network_error.js +++ b/jstests/noPassthrough/auto_retry_on_network_error.js @@ -61,28 +61,24 @@ const db = new Mongo(rst.getURL()).startSession({retryWrites: true}).getDatabase // 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.commandWorked(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); +assert.commandWorked(db.runCommand({ + insert: collName, + documents: [{x: 2}, {x: 3}], + txnNumber: NumberLong(10), + lsid: {id: UUID()} +})); // Retryable write commands that cannot be retried (i.e. no transaction number, no session id, // or are unordered) throw. @@ -93,11 +89,11 @@ assert.throws(function() { // 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); +assert.commandWorked(db.runCommand({ping: 1})); failNextCommand(db, "insert"); assert.throws(function() { - db.runCommandWithMetadata({insert: collName, documents: [{x: 1}, {x: 2}], ordered: false}, {}); + db.runCommand({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 @@ -111,7 +107,7 @@ assert.throws(function() { cursorId = assert.commandWorked(db.runCommand({find: collName, batchSize: 0})).cursor.id; failNextCommand(db, "getMore"); assert.throws(function() { - db.runCommandWithMetadata({getMore: cursorId, collection: collName}, {}); + db.runCommand({getMore: cursorId, collection: collName}); }); rst.stopSet(); diff --git a/jstests/replsets/last_op_visible.js b/jstests/replsets/last_op_visible.js index b3b6a7c4bcf..ae0354300fa 100644 --- a/jstests/replsets/last_op_visible.js +++ b/jstests/replsets/last_op_visible.js @@ -16,34 +16,31 @@ replTest.initiate(); var primary = replTest.getPrimary(); // Do an insert without writeConcern. -var res = primary.getDB(name).runCommandWithMetadata({insert: name, documents: [{x: 1}]}, - {"$replData": 1}); -assert.commandWorked(res.commandReply); -var last_op_visible = res.commandReply["$replData"].lastOpVisible; +var res = primary.getDB(name).runCommand({insert: name, documents: [{x: 1}], $replData: 1}); +assert.commandWorked(res); +var last_op_visible = res["$replData"].lastOpVisible; // A find should return the same lastVisibleOp. -res = primary.getDB(name).runCommandWithMetadata({find: name, readConcern: {level: "local"}}, - {"$replData": 1}); -assert.commandWorked(res.commandReply); -assert.eq(last_op_visible, res.commandReply["$replData"].lastOpVisible); +res = primary.getDB(name).runCommand({find: name, readConcern: {level: "local"}, $replData: 1}); +assert.commandWorked(res); +assert.eq(last_op_visible, res["$replData"].lastOpVisible); // A majority readConcern with afterOpTime: lastOpVisible should also return the same // lastVisibleOp. -res = primary.getDB(name).runCommandWithMetadata( - {find: name, readConcern: {level: "majority", afterOpTime: last_op_visible}}, {"$replData": 1}); -assert.commandWorked(res.commandReply); -assert.eq(last_op_visible, res.commandReply["$replData"].lastOpVisible); +res = primary.getDB(name).runCommand( + {find: name, readConcern: {level: "majority", afterOpTime: last_op_visible}, $replData: 1}); +assert.commandWorked(res); +assert.eq(last_op_visible, res["$replData"].lastOpVisible); // Do an insert without writeConcern. -res = primary.getDB(name).runCommandWithMetadata( - {insert: name, documents: [{x: 1}], writeConcern: {w: "majority"}}, {"$replData": 1}); -assert.commandWorked(res.commandReply); -last_op_visible = res.commandReply["$replData"].lastOpVisible; +res = primary.getDB(name).runCommand( + {insert: name, documents: [{x: 1}], writeConcern: {w: "majority"}, $replData: 1}); +assert.commandWorked(res); +last_op_visible = res["$replData"].lastOpVisible; // A majority readConcern should return the same lastVisibleOp. -res = primary.getDB(name).runCommandWithMetadata({find: name, readConcern: {level: "majority"}}, - {"$replData": 1}); -assert.commandWorked(res.commandReply); -assert.eq(last_op_visible, res.commandReply["$replData"].lastOpVisible); +res = primary.getDB(name).runCommand({find: name, readConcern: {level: "majority"}, $replData: 1}); +assert.commandWorked(res); +assert.eq(last_op_visible, res["$replData"].lastOpVisible); replTest.stopSet(); }()); diff --git a/jstests/replsets/read_committed_no_snapshots.js b/jstests/replsets/read_committed_no_snapshots.js index 280b0de7d49..b8d09dfda80 100644 --- a/jstests/replsets/read_committed_no_snapshots.js +++ b/jstests/replsets/read_committed_no_snapshots.js @@ -43,18 +43,18 @@ var noSnapshotSecondary = secondaries[1]; noSnapshotSecondary.setSecondaryOk(); // Do a write, wait for it to replicate, and ensure it is visible. -var res = primary.getDB(name).runCommandWithMetadata( // +var res = primary.getDB(name).runCommand( // { insert: "foo", documents: [{_id: 1, state: 0}], - writeConcern: {w: "majority", wtimeout: ReplSetTest.kDefaultTimeoutMS} - }, - {"$replData": 1}); -assert.commandWorked(res.commandReply); + writeConcern: {w: "majority", wtimeout: ReplSetTest.kDefaultTimeoutMS}, + $replData: 1 + }); +assert.commandWorked(res); // We need to propagate the lastOpVisible from the primary as afterOpTime in the secondaries to // ensure we wait for the write to be in the majority committed view. -var lastOp = res.commandReply["$replData"].lastOpVisible; +var lastOp = res["$replData"].lastOpVisible; // Timeout is based on heartbeat timeout. assert.commandWorked(healthySecondary.getDB(name).foo.runCommand( diff --git a/jstests/replsets/read_committed_on_secondary.js b/jstests/replsets/read_committed_on_secondary.js index da29020b101..5ac19c0d8bd 100644 --- a/jstests/replsets/read_committed_on_secondary.js +++ b/jstests/replsets/read_committed_on_secondary.js @@ -57,17 +57,17 @@ var collSecondary = dbSecondary[name]; function saveDoc(state) { log("saving doc."); - var res = dbPrimary.runCommandWithMetadata( // + var res = dbPrimary.runCommand( // { update: name, writeConcern: {w: 2, wtimeout: ReplSetTest.kDefaultTimeoutMS}, updates: [{q: {_id: 1}, u: {_id: 1, state: state}, upsert: true}], - }, - {"$replData": 1}); - assert.commandWorked(res.commandReply); - assert.eq(res.commandReply.writeErrors, undefined); - log("done saving doc: optime " + tojson(res.commandReply.$replData.lastOpVisible)); - return res.commandReply.$replData.lastOpVisible; + $replData: 1 + }); + assert.commandWorked(res); + assert.eq(res.writeErrors, undefined); + log("done saving doc: optime " + tojson(res.$replData.lastOpVisible)); + return res.$replData.lastOpVisible; } function doDirtyRead(lastOp) { diff --git a/jstests/sharding/auth_sharding_cmd_metadata.js b/jstests/sharding/auth_sharding_cmd_metadata.js index 76b582ec0fe..548f65ee01a 100644 --- a/jstests/sharding/auth_sharding_cmd_metadata.js +++ b/jstests/sharding/auth_sharding_cmd_metadata.js @@ -32,15 +32,12 @@ const shardTestDB = st.rs0.getPrimary().getDB('test'); shardAdminDB.createUser({user: 'user', pwd: 'pwd', roles: jsTest.adminUserRoles}); shardAdminDB.auth('user', 'pwd'); const newTimestamp = Timestamp(getConfigOpTime().getTime() + 1000, 0); -const metadata = { - $configTime: newTimestamp -}; -assert.commandWorked(shardTestDB.runCommandWithMetadata({ping: 1}, metadata).commandReply); +assert.commandWorked(shardTestDB.runCommand({ping: 1, $configTime: newTimestamp})); assert(timestampCmp(getConfigOpTime(), newTimestamp) < 0, "Unexpected ConfigOpTime advancement"); shardAdminDB.createUser({user: 'internal', pwd: 'pwd', roles: ['__system']}); shardAdminDB.auth('internal', 'pwd'); -assert.commandWorked(shardTestDB.runCommandWithMetadata({ping: 1}, metadata).commandReply); +assert.commandWorked(shardTestDB.runCommand({ping: 1, $configTime: newTimestamp})); assert(timestampCmp(getConfigOpTime(), newTimestamp) < 0, "Unexpected ConfigOpTime advancement"); mongosAdminDB.logout(); diff --git a/src/mongo/scripting/mozjs/mongo.cpp b/src/mongo/scripting/mozjs/mongo.cpp index 0c758aab00a..58325932609 100644 --- a/src/mongo/scripting/mozjs/mongo.cpp +++ b/src/mongo/scripting/mozjs/mongo.cpp @@ -77,7 +77,6 @@ const JSFunctionSpec MongoBase::methods[] = { MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(isTLS, MongoExternalInfo), MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(getApiParameters, MongoExternalInfo), MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(_runCommandImpl, MongoExternalInfo), - MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(_runCommandWithMetadataImpl, MongoExternalInfo), MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(_startSession, MongoExternalInfo), JS_FS_END, }; @@ -235,8 +234,6 @@ namespace { /** * Common implementation for: * object Mongo._runCommandImpl(string dbname, object cmd, int options, object token) - * object Mongo._runCommandWithMetadataImpl(string dbname, object metadata, object commandArgs, - * object token) * * Extra is for connection-wide metadata to pass with any given runCommand. */ @@ -317,21 +314,6 @@ void MongoBase::Functions::_runCommandImpl::call(JSContext* cx, JS::CallArgs arg }); } -struct RunCommandWithMetadataParams { - static constexpr bool kHoistReply = true; - static constexpr auto kCommandName = "runCommandWithMetadata"_sd; - static constexpr auto kArg1Name = "metadata"_sd; -}; - -void MongoBase::Functions::_runCommandWithMetadataImpl::call(JSContext* cx, JS::CallArgs args) { - doRunCommand<RunCommandWithMetadataParams>(cx, args, [&](StringData db, BSONObj metadata) { - uassert(ErrorCodes::BadValue, - str::stream() << "The commandArgs parameter to runCommand must be an object", - args.get(2).isObject()); - return OpMsgRequest::fromDBAndBody(db, ValueWriter(cx, args.get(2)).toBSON(), metadata); - }); -} - void MongoBase::Functions::find::call(JSContext* cx, JS::CallArgs args) { auto scope = getScope(cx); diff --git a/src/mongo/scripting/mozjs/mongo.h b/src/mongo/scripting/mozjs/mongo.h index 248a5b2a5ae..f7d05742568 100644 --- a/src/mongo/scripting/mozjs/mongo.h +++ b/src/mongo/scripting/mozjs/mongo.h @@ -74,7 +74,6 @@ struct MongoBase : public BaseInfo { MONGO_DECLARE_JS_FUNCTION(isTLS); MONGO_DECLARE_JS_FUNCTION(getApiParameters); MONGO_DECLARE_JS_FUNCTION(_runCommandImpl); - MONGO_DECLARE_JS_FUNCTION(_runCommandWithMetadataImpl); MONGO_DECLARE_JS_FUNCTION(_startSession); }; diff --git a/src/mongo/shell/mongo.js b/src/mongo/shell/mongo.js index 955cbcd4a9e..850898de02d 100644 --- a/src/mongo/shell/mongo.js +++ b/src/mongo/shell/mongo.js @@ -167,10 +167,6 @@ Mongo.prototype.runCommand = function(dbname, cmd, options) { return this._runCommandImpl(dbname, cmd, options, this._securityToken); }; -Mongo.prototype.runCommandWithMetadata = function(dbname, metadata, cmd) { - return this._runCommandWithMetadataImpl(dbname, metadata, cmd, this._securityToken); -}; - /** * Returns all log components and current verbosity values */ diff --git a/src/mongo/shell/session.js b/src/mongo/shell/session.js index f54a73bb186..7fa361db56b 100644 --- a/src/mongo/shell/session.js +++ b/src/mongo/shell/session.js @@ -471,17 +471,6 @@ var { processCommandResponse(driverSession, client, res); return res; }; - - this.runCommandWithMetadata = function runCommandWithMetadata( - driverSession, dbName, metadata, cmdObj) { - cmdObj = this.prepareCommandRequest(driverSession, cmdObj); - - const res = runClientFunctionWithRetries( - driverSession, cmdObj, client.runCommandWithMetadata, [dbName, metadata, cmdObj]); - - processCommandResponse(driverSession, client, res); - return res; - }; } function TransactionOptions(rawOptions = {}) { |