mirror of https://github.com/mongodb/mongo
105 lines
4.1 KiB
JavaScript
105 lines
4.1 KiB
JavaScript
/**
|
|
* Test that initial sync fails if a rollback occurs while querying collection data.
|
|
*
|
|
* This test depends on 4.4 features.
|
|
* @tags: [multiversion_incompatible]
|
|
*/
|
|
import {configureFailPoint} from "jstests/libs/fail_point_util.js";
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
|
import {RollbackTest} from "jstests/replsets/libs/rollback_test.js";
|
|
|
|
const testName = "initial_sync_fails_on_rollback";
|
|
const dbName = testName;
|
|
|
|
// Operations that will be present on both nodes, before the common point.
|
|
let CommonOps = (node) => {
|
|
let testDb = node.getDB(dbName);
|
|
let bulk = testDb.test.initializeOrderedBulkOp();
|
|
for (let i = 0; i < 100; i++) {
|
|
bulk.insert({a: i});
|
|
}
|
|
assert.commandWorked(bulk.execute({w: "majority"}));
|
|
};
|
|
|
|
// Operations that will be performed on the rollback node past the common point.
|
|
let RollbackOps = (node) => {
|
|
let testDb = node.getDB(dbName);
|
|
assert.commandWorked(testDb.test.insert({b: 1}));
|
|
};
|
|
|
|
// Set up Rollback Test.
|
|
let rollbackTest = new RollbackTest(testName);
|
|
CommonOps(rollbackTest.getPrimary());
|
|
|
|
// Add the initial sync node.
|
|
const initialSyncNode = rollbackTest.add({
|
|
config: {
|
|
// This node must be non-voting to avoid interfering with the rollback machinery.
|
|
rsConfig: {priority: 0, votes: 0},
|
|
setParameter: {
|
|
"failpoint.initialSyncHangBeforeCopyingDatabases": tojson({mode: "alwaysOn"}),
|
|
"collectionClonerBatchSize": 10,
|
|
// This test is specifically testing that the cloners stop, so we turn off the
|
|
// oplog fetcher to ensure that we don't inadvertently test that instead.
|
|
"failpoint.hangBeforeStartingOplogFetcher": tojson({mode: "alwaysOn"}),
|
|
// Make sure our initial sync node only talks to the rolling-back primary.
|
|
"failpoint.forceSyncSourceCandidate": tojson({
|
|
mode: "alwaysOn",
|
|
data: {"hostAndPort": rollbackTest.getPrimary().host},
|
|
}),
|
|
"numInitialSyncAttempts": 1,
|
|
},
|
|
},
|
|
});
|
|
|
|
jsTestLog("Waiting for initial sync node to reach initial sync state");
|
|
const rst = rollbackTest.getTestFixture();
|
|
rst.waitForState(initialSyncNode, ReplSetTest.State.STARTUP_2);
|
|
|
|
const afterBatchResponseFailPoint = configureFailPoint(
|
|
initialSyncNode,
|
|
"initialSyncHangCollectionClonerAfterHandlingBatchResponse",
|
|
{nss: dbName + ".test"},
|
|
);
|
|
const beforeFinishFailPoint = configureFailPoint(initialSyncNode, "initialSyncHangBeforeFinish");
|
|
// Release the initial failpoint.
|
|
assert.commandWorked(
|
|
initialSyncNode.adminCommand({configureFailPoint: "initialSyncHangBeforeCopyingDatabases", mode: "off"}),
|
|
);
|
|
|
|
jsTestLog("Waiting for CollectionCloner to reach " + dbName + ".test collection");
|
|
afterBatchResponseFailPoint.wait();
|
|
|
|
jsTestLog("Rolling back");
|
|
let rollbackNode = rollbackTest.transitionToRollbackOperations();
|
|
RollbackOps(rollbackNode);
|
|
|
|
// Wait for rollback to finish.
|
|
rollbackTest.transitionToSyncSourceOperationsBeforeRollback();
|
|
rollbackTest.transitionToSyncSourceOperationsDuringRollback();
|
|
// We must skip consistency checks because our initial sync node is not consistent.
|
|
rollbackTest.transitionToSteadyStateOperations({skipDataConsistencyChecks: true});
|
|
|
|
jsTestLog("Releasing the CollectionCloner failpoint.");
|
|
afterBatchResponseFailPoint.off();
|
|
|
|
jsTestLog("Releasing the oplog fetcher failpoint.");
|
|
assert.commandWorked(
|
|
initialSyncNode.getDB("test").adminCommand({configureFailPoint: "hangBeforeStartingOplogFetcher", mode: "off"}),
|
|
);
|
|
|
|
beforeFinishFailPoint.wait();
|
|
const res = assert.commandWorked(initialSyncNode.adminCommand({replSetGetStatus: 1}));
|
|
// The initial sync should have failed.
|
|
assert.eq(res.initialSyncStatus.failedInitialSyncAttempts, 1);
|
|
// It should have determined the correct number of documents to copy.
|
|
assert.eq(res.initialSyncStatus.databases[dbName][dbName + ".test"].documentsToCopy, 100);
|
|
// No more than one batch should have been copied.
|
|
assert.lte(res.initialSyncStatus.databases[dbName][dbName + ".test"].documentsCopied, 10);
|
|
|
|
// Get rid of the failed node so the fixture can stop properly.
|
|
rst.stop(initialSyncNode);
|
|
rst.remove(initialSyncNode);
|
|
|
|
rollbackTest.stop();
|