diff options
author | Drew Paroski <drew.paroski@mongodb.com> | 2020-05-11 12:30:47 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-11 18:12:38 +0000 |
commit | ff441d6e3f30a5c6a779d416409a46d35d9c26b7 (patch) | |
tree | fc73e3b51140b965a1ae46e578a8b406fc973d00 | |
parent | e6dcc106ab333e7f2a96ea9f92d0c9fad6ff0da7 (diff) | |
download | mongo-ff441d6e3f30a5c6a779d416409a46d35d9c26b7.tar.gz |
SERVER-46686 Update explain() shell command to propagate "maxTimeMS" arg to top-level, take 2
-rw-r--r-- | jstests/noPassthrough/explain_max_time_ms.js | 82 | ||||
-rw-r--r-- | src/mongo/shell/explain_query.js | 5 | ||||
-rw-r--r-- | src/mongo/shell/explainable.js | 21 |
3 files changed, 104 insertions, 4 deletions
diff --git a/jstests/noPassthrough/explain_max_time_ms.js b/jstests/noPassthrough/explain_max_time_ms.js new file mode 100644 index 00000000000..728d0f3c144 --- /dev/null +++ b/jstests/noPassthrough/explain_max_time_ms.js @@ -0,0 +1,82 @@ +/** + * Tests the explain command with the maxTimeMS option. + */ +(function() { +"use strict"; + +const standalone = MongoRunner.runMongod(); +assert.neq(null, standalone, "mongod was unable to start up"); + +const dbName = "test"; +const db = standalone.getDB(dbName); +const collName = "explain_max_time_ms"; +const coll = db.getCollection(collName); + +const destCollName = "explain_max_time_ms_dest"; +const mapFn = function() { + emit(this.i, this.j); +}; +const reduceFn = function(key, values) { + return Array.sum(values); +}; + +coll.drop(); +assert.commandWorked(db.createCollection(collName)); + +assert.commandWorked(coll.insert({i: 1, j: 1})); +assert.commandWorked(coll.insert({i: 2, j: 1})); +assert.commandWorked(coll.insert({i: 2, j: 2})); + +// Set fail point to make sure operations with "maxTimeMS" set will time out. +assert.commandWorked( + db.adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "alwaysOn"})); + +for (const verbosity of ["executionStats", "allPlansExecution"]) { + // Expect explain to time out if "maxTimeMS" is set on the aggregate command. + assert.commandFailedWithCode(assert.throws(function() { + coll.explain(verbosity).aggregate( + [{$match: {i: 1}}], {maxTimeMS: 1}); + }), + ErrorCodes.MaxTimeMSExpired); + // Expect explain to time out if "maxTimeMS" is set on the count command. + assert.commandFailedWithCode(assert.throws(function() { + coll.explain(verbosity).count({i: 1}, + {maxTimeMS: 1}); + }), + ErrorCodes.MaxTimeMSExpired); + // Expect explain to time out if "maxTimeMS" is set on the distinct command. + assert.commandFailedWithCode(assert.throws(function() { + coll.explain(verbosity).distinct( + "i", {}, {maxTimeMS: 1}); + }), + ErrorCodes.MaxTimeMSExpired); + // Expect explain to time out if "maxTimeMS" is set on the find command. + assert.commandFailedWithCode(assert.throws(function() { + coll.find().maxTimeMS(1).explain(verbosity); + }), + ErrorCodes.MaxTimeMSExpired); + assert.commandFailedWithCode( + assert.throws(function() { + coll.explain(verbosity).find().maxTimeMS(1).finish(); + }), + ErrorCodes.MaxTimeMSExpired); + // Expect explain to time out if "maxTimeMS" is set on the findAndModify command. + assert.commandFailedWithCode(assert.throws(function() { + coll.explain(verbosity).findAndModify( + {update: {$inc: {j: 1}}, maxTimeMS: 1}); + }), + ErrorCodes.MaxTimeMSExpired); + // Expect explain to time out if "maxTimeMS" is set on the mapReduce command. + assert.commandFailedWithCode( + assert.throws(function() { + coll.explain(verbosity).mapReduce( + mapFn, reduceFn, {out: destCollName, maxTimeMS: 1}); + }), + ErrorCodes.MaxTimeMSExpired); +} + +// Disable fail point. +assert.commandWorked(db.adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "off"})); + +MongoRunner.stopMongod(standalone); +})(); diff --git a/src/mongo/shell/explain_query.js b/src/mongo/shell/explain_query.js index c679683a421..b4935fd07d4 100644 --- a/src/mongo/shell/explain_query.js +++ b/src/mongo/shell/explain_query.js @@ -151,6 +151,11 @@ var DBExplainQuery = (function() { var explainCmd = {explain: innerCmd}; explainCmd["verbosity"] = this._verbosity; + // If "maxTimeMS" is set on innerCmd, it needs to be propagated to the top-level + // of explainCmd so that it has the intended effect. + if (innerCmd.hasOwnProperty("maxTimeMS")) { + explainCmd.maxTimeMS = innerCmd.maxTimeMS; + } var explainDb = this._query._db; diff --git a/src/mongo/shell/explainable.js b/src/mongo/shell/explainable.js index 08a900c5274..c47c7fab7cd 100644 --- a/src/mongo/shell/explainable.js +++ b/src/mongo/shell/explainable.js @@ -35,6 +35,16 @@ var Explainable = (function() { return explainResult; }; + var buildExplainCmd = function(innerCmd, verbosity) { + var explainCmd = {"explain": innerCmd, "verbosity": verbosity}; + // If "maxTimeMS" is set on innerCmd, it needs to be propagated to the top-level + // of explainCmd so that it has the intended effect. + if (innerCmd.hasOwnProperty("maxTimeMS")) { + explainCmd.maxTimeMS = innerCmd.maxTimeMS; + } + return explainCmd; + }; + function constructor(collection, verbosity) { // // Private vars. @@ -117,7 +127,7 @@ var Explainable = (function() { let aggCmd = Object.extend( {"aggregate": this._collection.getName(), "pipeline": pipeline}, extraOptsCopy); - let explainCmd = {"explain": aggCmd, "verbosity": this._verbosity}; + let explainCmd = buildExplainCmd(aggCmd, this._verbosity); let explainResult = this._collection.runReadCommand(explainCmd); return throwOrReturn(explainResult); } @@ -140,7 +150,7 @@ var Explainable = (function() { this.findAndModify = function(params) { var famCmd = Object.extend({"findAndModify": this._collection.getName()}, params); - var explainCmd = {"explain": famCmd, "verbosity": this._verbosity}; + var explainCmd = buildExplainCmd(famCmd, this._verbosity); var explainResult = this._collection.runReadCommand(explainCmd); return throwOrReturn(explainResult); }; @@ -155,8 +165,11 @@ var Explainable = (function() { if (options && options.hasOwnProperty("collation")) { distinctCmd.collation = options.collation; } + if (options && options.hasOwnProperty("maxTimeMS")) { + distinctCmd.maxTimeMS = options.maxTimeMS; + } - var explainCmd = {explain: distinctCmd, verbosity: this._verbosity}; + var explainCmd = buildExplainCmd(distinctCmd, this._verbosity); var explainResult = this._collection.runReadCommand(explainCmd); return throwOrReturn(explainResult); }; @@ -235,7 +248,7 @@ var Explainable = (function() { else Object.extend(mapReduceCmd, optionsObjOrOutString); - const explainCmd = {"explain": mapReduceCmd, "verbosity": this._verbosity}; + const explainCmd = buildExplainCmd(mapReduceCmd, this._verbosity); const explainResult = this._collection.runCommand(explainCmd); return throwOrReturn(explainResult); }; |