mirror of https://github.com/mongodb/mongo
104 lines
4.0 KiB
JavaScript
104 lines
4.0 KiB
JavaScript
/**
|
|
* This test shuts down a replica set during a two-phase index build. The test corrupts a WiredTiger
|
|
* collection file and expects that --repair salvages the data and drops the unfinished index.
|
|
*
|
|
* @tags: [requires_wiredtiger, requires_replication]
|
|
*/
|
|
|
|
import {
|
|
assertErrorOnStartupWhenStartingAsReplSet,
|
|
assertRepairSucceeds,
|
|
assertStartInReplSet,
|
|
corruptFile,
|
|
getUriForColl,
|
|
startMongodOnExistingPath,
|
|
} from "jstests/disk/libs/wt_file_helper.js";
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
|
import {IndexBuildTest} from "jstests/noPassthrough/libs/index_builds/index_build.js";
|
|
|
|
const dbName = "repair_unfinished_indexes";
|
|
const collName = "test";
|
|
|
|
const replSet = new ReplSetTest({nodes: 2});
|
|
replSet.startSet();
|
|
replSet.initiate(null, null, {initiateWithDefaultElectionTimeout: true});
|
|
|
|
const primary = replSet.getPrimary();
|
|
const primaryDB = primary.getDB(dbName);
|
|
|
|
const secondary = replSet.getSecondary();
|
|
const secondaryDB = secondary.getDB(dbName);
|
|
const secondaryPort = secondary.port;
|
|
const secondaryDbpath = secondary.dbpath;
|
|
|
|
const primaryColl = primaryDB.getCollection(collName);
|
|
|
|
assert.commandWorked(primaryColl.insert({_id: 0, a: 1}));
|
|
|
|
jsTestLog("Starting index build on primary and pausing before completion");
|
|
IndexBuildTest.pauseIndexBuilds(primary);
|
|
const createIdx = IndexBuildTest.startIndexBuild(primary, primaryColl.getFullName(), {a: 1});
|
|
|
|
jsTestLog("Waiting for secondary to start the index build");
|
|
IndexBuildTest.waitForIndexBuildToStart(secondaryDB);
|
|
|
|
const secondaryCollUri = getUriForColl(secondaryDB[collName]);
|
|
replSet.stop(secondary);
|
|
|
|
// Confirm that the secondary node leaves the index as unfinished.
|
|
(function startAsStandalone() {
|
|
jsTestLog("Starting secondary as standalone");
|
|
const mongod = startMongodOnExistingPath(
|
|
secondaryDbpath,
|
|
// This parameter ensures that when the standalone starts up, it applies all unapplied oplog
|
|
// entries since the last shutdown. This "smooths out" a race condition in this test where
|
|
// the secondary can shut down without fully applying the 'startIndexBuild' oplog entry, and
|
|
// not advancing the stable timestamp to the top of the oplog.
|
|
{setParameter: "recoverFromOplogAsStandalone=true"},
|
|
);
|
|
IndexBuildTest.assertIndexes(mongod.getDB(dbName).getCollection(collName), 2, ["_id_"], ["a_1"], {
|
|
includeBuildUUIDs: true,
|
|
});
|
|
MongoRunner.stopMongod(mongod);
|
|
})();
|
|
|
|
const exitCode = createIdx({checkExitSuccess: false});
|
|
assert.neq(0, exitCode, "expected shell to exit abnormally due to shutdown");
|
|
|
|
const secondaryCollFile = secondaryDbpath + "/" + secondaryCollUri + ".wt";
|
|
jsTestLog("Corrupting secondary collection file: " + secondaryCollFile);
|
|
corruptFile(secondaryCollFile);
|
|
assertRepairSucceeds(secondaryDbpath, secondaryPort);
|
|
|
|
// Importantly, confirm that the secondary node dropped the unfinished index.
|
|
(function startAsStandaloneAfterRepair() {
|
|
jsTestLog("Starting secondary as standalone after repair");
|
|
const mongod = startMongodOnExistingPath(secondaryDbpath);
|
|
IndexBuildTest.assertIndexes(mongod.getDB(dbName).getCollection(collName), 1, ["_id_"], [], {
|
|
includeBuildUUIDs: true,
|
|
});
|
|
MongoRunner.stopMongod(mongod);
|
|
})();
|
|
|
|
// The secondary may not be reintroduced because data was modified.
|
|
assertErrorOnStartupWhenStartingAsReplSet(secondaryDbpath, secondaryPort, replSet.getReplSetConfig()._id);
|
|
|
|
(function reSyncSecondary() {
|
|
jsTestLog("Wiping dbpath and re-syncing secondary");
|
|
const newSecondary = assertStartInReplSet(
|
|
replSet,
|
|
secondary,
|
|
true /* cleanData */,
|
|
true /* expectResync */,
|
|
function (node) {},
|
|
);
|
|
|
|
IndexBuildTest.resumeIndexBuilds(primary);
|
|
IndexBuildTest.waitForIndexBuildToStop(primaryDB);
|
|
replSet.awaitReplication();
|
|
IndexBuildTest.assertIndexes(primaryColl, 2, ["_id_", "a_1"]);
|
|
IndexBuildTest.assertIndexes(newSecondary.getDB(dbName).getCollection(collName), 2, ["_id_", "a_1"]);
|
|
})();
|
|
|
|
replSet.stopSet();
|