Files
mongo/jstests/serverless/shard_split_donor_current_op.js

171 lines
5.7 KiB
JavaScript

/**
* Tests currentOp command during a shard split.
*
* Shard splits are not expected to be run on servers with ephemeralForTest.
*
* @tags: [
* incompatible_with_eft,
* incompatible_with_macos,
* incompatible_with_windows_tls,
* requires_majority_read_concern,
* requires_persistence,
* serverless,
* requires_fcv_62
* ]
*/
import {ShardSplitTest} from "jstests/serverless/libs/shard_split_test.js";
load("jstests/libs/fail_point_util.js");
const kTenantIds = [ObjectId()];
function checkStandardFieldsOK(ops, {migrationId, reachedDecision, tenantIds}) {
assert.eq(ops.length, 1);
const [op] = ops;
assert.eq(bsonWoCompare(op.instanceID, migrationId), 0);
assert.eq(op.reachedDecision, reachedDecision);
if (tenantIds) {
// we need to convert tenantIds to an array of string objects.
let tenantIdsStrings = [];
tenantIds.forEach(tenantId => {
tenantIdsStrings.push(tenantId.str);
});
assert.eq(bsonWoCompare(op.tenantIds, tenantIdsStrings), 0);
}
}
(() => {
jsTestLog("Testing currentOp output for split before blocking state");
const test =
new ShardSplitTest({recipientTagName: "recipientTag", recipientSetName: "recipientSet"});
test.addRecipientNodes();
const operation = test.createSplitOperation(kTenantIds);
const donorPrimary = test.donor.getPrimary();
let fp = configureFailPoint(donorPrimary, "pauseShardSplitBeforeBlockingState");
const splitThread = operation.commitAsync();
fp.wait();
const res = assert.commandWorked(
donorPrimary.adminCommand({currentOp: true, desc: "shard split operation"}));
print(`CURR_OP: ${tojson(res)}`);
checkStandardFieldsOK(
res.inprog,
{migrationId: operation.migrationId, reachedDecision: false, tenantIds: kTenantIds});
assert(!res.inprog[0].blockOpTime);
fp.off();
splitThread.join();
assert.commandWorked(splitThread.returnData());
test.removeAndStopRecipientNodes();
test.stop();
})();
(() => {
jsTestLog("Testing currentOp output for split in blocking state");
const test =
new ShardSplitTest({recipientTagName: "recipientTag", recipientSetName: "recipientSet"});
test.addRecipientNodes();
const operation = test.createSplitOperation(kTenantIds);
const donorPrimary = test.donor.getPrimary();
let fp = configureFailPoint(donorPrimary, "pauseShardSplitAfterBlocking");
const splitThread = operation.commitAsync();
fp.wait();
const res = assert.commandWorked(
donorPrimary.adminCommand({currentOp: true, desc: "shard split operation"}));
checkStandardFieldsOK(
res.inprog,
{migrationId: operation.migrationId, reachedDecision: false, tenantIds: kTenantIds});
assert(res.inprog[0].blockOpTime.ts instanceof Timestamp);
fp.off();
splitThread.join();
assert.commandWorked(splitThread.returnData());
test.removeAndStopRecipientNodes();
test.stop();
})();
(() => {
jsTestLog("Testing currentOp output for aborted split");
const test =
new ShardSplitTest({recipientTagName: "recipientTag", recipientSetName: "recipientSet"});
test.addRecipientNodes();
const operation = test.createSplitOperation(kTenantIds);
assert.commandWorked(operation.abort());
const res = assert.commandWorked(
test.donor.getPrimary().adminCommand({currentOp: true, desc: "shard split operation"}));
checkStandardFieldsOK(
res.inprog, {migrationId: operation.migrationId, reachedDecision: true, tenantIds: null});
assert(res.inprog[0].commitOrAbortOpTime.ts instanceof Timestamp);
assert(res.inprog[0].commitOrAbortOpTime.t instanceof NumberLong);
assert.eq(typeof res.inprog[0].abortReason.code, "number");
assert.eq(typeof res.inprog[0].abortReason.codeName, "string");
assert.eq(typeof res.inprog[0].abortReason.errmsg, "string");
assert(res.inprog[0].expireAt instanceof Date);
test.stop();
})();
// Check currentOp while in committed state before and after a split has completed.
(() => {
jsTestLog("Testing currentOp output for committed split");
const test =
new ShardSplitTest({recipientTagName: "recipientTag", recipientSetName: "recipientSet"});
test.addRecipientNodes();
const donorPrimary = test.donor.getPrimary();
const operation = test.createSplitOperation(kTenantIds);
assert.commandWorked(operation.commit());
let res = donorPrimary.adminCommand({currentOp: true, desc: "shard split operation"});
checkStandardFieldsOK(
res.inprog,
{migrationId: operation.migrationId, reachedDecision: true, tenantIds: kTenantIds});
assert(res.inprog[0].blockOpTime.ts instanceof Timestamp);
assert(res.inprog[0].commitOrAbortOpTime.ts instanceof Timestamp);
assert(res.inprog[0].commitOrAbortOpTime.t instanceof NumberLong);
assert(!res.inprog[0].expireAt);
assert.eq(res.inprog[0].recipientSetName, operation.recipientSetName);
assert.eq(res.inprog[0].recipientTagName, operation.recipientTagName);
assert(res.inprog[0].recipientConnectionString);
jsTestLog("Testing currentOp output for a committed split after forgetShardSplit");
test.removeAndStopRecipientNodes();
operation.forget();
res = test.donor.getPrimary().adminCommand({currentOp: true, desc: "shard split operation"});
jsTestLog("Checking");
checkStandardFieldsOK(
res.inprog,
{migrationId: operation.migrationId, reachedDecision: true, tenantIds: kTenantIds});
assert(res.inprog[0].blockOpTime.ts instanceof Timestamp);
assert(res.inprog[0].commitOrAbortOpTime.ts instanceof Timestamp);
assert(res.inprog[0].commitOrAbortOpTime.t instanceof NumberLong);
assert(res.inprog[0].expireAt instanceof Date);
test.stop();
})();