Files
mongo/jstests/core/currentop_shell.js

138 lines
4.6 KiB
JavaScript

/**
* Tests that the shell helper db.currentOpCursor isn't constrained by the legacy currentOp server
* command - ie. the result set isn't limited to 16MB and long operations aren't truncated.
*
* @tags: [
* uses_parallel_shell,
* # This test uses currentOp to check whether an aggregate command is running. In replica set
* # environments, because currentOp is run against the admin database it is routed to the
* # primary, while the aggregate may be routed to a secondary. If currentOp is running on one
* # node and the expected command is run on another, the latter will not show up in the
* # currentOp results.
* assumes_read_preference_unchanged,
* # The aggregation stage $currentOp cannot run with a readConcern other than 'local'
* assumes_read_concern_unchanged,
* requires_fcv_50
* ]
*/
(function() {
"use strict";
load("jstests/libs/fixture_helpers.js"); // for FixtureHelpers
const coll = db.currentOp_cursor;
coll.drop();
for (let i = 0; i < 3; i++) {
assert.commandWorked(coll.insert({val: 1}));
}
// Test that db.currentOpCursor() returns an iterable cursor.
let res = db.currentOpCursor();
assert(res.hasNext());
assert(res.next());
// Test that db.currentOp() interface does not change.
res = db.currentOp();
assert("inprog" in res, "Result contains 'inprog' field");
assert("ok" in res, "Result contains 'ok' field");
// Attempting to access the fsyncLock field from the results throws with an error message.
let error = assert.throws(() => res.fsyncLock);
assert(
/fsyncLock is no longer included in the currentOp shell helper, run db\.runCommand\({currentOp: 1}\) instead/
.test(error));
function shellOp() {
function createLargeDoc() {
let doc = {};
for (let i = 0; i < 100; i++) {
doc[i] = "Testing testing 1 2 3...";
}
return doc;
}
assert.commandFailedWithCode(db.runCommand({
aggregate: "currentOp_cursor",
pipeline: [{
$addFields: {
newVal: {$function: {args: [], body: "sleep(300000)", lang: "js"}},
bigDoc: createLargeDoc()
}
}],
cursor: {}
}),
ErrorCodes.Interrupted);
}
function startShellWithOp() {
const awaitShell = startParallelShell(shellOp);
// Confirm that the operation has started in the parallel shell.
assert.soon(
function() {
let aggRes = db.getSiblingDB("admin")
.aggregate([
{$currentOp: {allUsers: true, localOps: true}},
{$match: {ns: "test.currentOp_cursor"}}
])
.toArray();
return aggRes.length === 1;
},
function() {
return "Failed to find parallel shell operation in $currentOp output: " +
tojson(db.currentOp());
});
return awaitShell;
}
// Test that the currentOp server command truncates long operations with a warning logged.
const serverCommandTest = startShellWithOp();
res = db.adminCommand({currentOp: true, "ns": "test.currentOp_cursor", $all: true});
if (FixtureHelpers.isMongos(db) && FixtureHelpers.isSharded(coll)) {
// Assert currentOp truncation behavior for each shard in the cluster.
assert(res.inprog.length >= 1);
res.inprog.forEach((result) => {
assert.eq(result.op, "getmore");
assert(result.cursor.originatingCommand.hasOwnProperty("$truncated"));
});
} else {
// Assert currentOp truncation behavior for unsharded collections.
assert.eq(res.inprog.length, 1);
assert.eq(res.inprog[0].op, "command");
assert(res.inprog[0].command.hasOwnProperty("$truncated"));
}
const log = FixtureHelpers.getPrimaryForNodeHostingDatabase(db).adminCommand({getLog: "global"});
assert(/will be truncated/.test(log.log));
res.inprog.forEach((op) => {
assert.commandWorked(db.killOp(op.opid));
});
serverCommandTest();
// Test that the db.currentOp() shell helper does not truncate ops.
const shellHelperTest = startShellWithOp();
res = db.currentOp({"ns": "test.currentOp_cursor"});
if (FixtureHelpers.isMongos(db) && FixtureHelpers.isSharded(coll)) {
assert(res.inprog.length >= 1);
res.inprog.forEach((result) => {
assert.eq(result.op, "getmore");
assert(!result.cursor.originatingCommand.hasOwnProperty("$truncated"));
});
} else {
assert.eq(res.inprog.length, 1);
assert(!res.inprog[0].command.hasOwnProperty("$truncated"));
}
res.inprog.forEach((op) => {
assert.commandWorked(db.killOp(op.opid));
});
shellHelperTest();
})();