summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew Paroski <drew.paroski@mongodb.com>2020-05-11 12:30:47 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-05-11 18:12:38 +0000
commitff441d6e3f30a5c6a779d416409a46d35d9c26b7 (patch)
treefc73e3b51140b965a1ae46e578a8b406fc973d00
parente6dcc106ab333e7f2a96ea9f92d0c9fad6ff0da7 (diff)
downloadmongo-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.js82
-rw-r--r--src/mongo/shell/explain_query.js5
-rw-r--r--src/mongo/shell/explainable.js21
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);
};