mongo/jstests/replsets/secondary_as_sync_source.js

128 lines
4.0 KiB
JavaScript

/**
* Tests that a new replica set member performing an initial sync from a secondary node as the sync
* source, which has an in-progress index build will also build the index as part of the initial
* sync operation.
*
* @tags: [
* requires_fcv_60,
* requires_replication,
* ]
*/
(function() {
'use strict';
load("jstests/core/timeseries/libs/timeseries.js");
load('jstests/noPassthrough/libs/index_build.js');
load("jstests/replsets/rslib.js");
const dbName = "test";
const collName = "coll";
const timeseriesCollName = "tscoll";
function addTestDocuments(coll) {
let size = 100;
jsTest.log("Creating " + size + " test documents.");
var bulk = coll.initializeUnorderedBulkOp();
for (var i = 0; i < size; ++i) {
bulk.insert({i: i});
}
assert.commandWorked(bulk.execute());
}
const replSet = new ReplSetTest({
nodes: [
{},
{
// Disallow elections on secondary.
rsConfig: {
priority: 0,
votes: 0,
},
slowms: 30000, // Don't log slow operations on secondary. See SERVER-44821.
},
],
useBridge: true,
});
const nodes = replSet.startSet();
replSet.initiate();
let primary = replSet.getPrimary();
let primaryDB = primary.getDB(dbName);
let secondary = replSet.getSecondary();
let secondaryDB = secondary.getDB(dbName);
const coll = primaryDB.getCollection(collName);
addTestDocuments(coll);
// Create time-series collection with a single measurement.
// We need a non-empty collection to use two-phase index builds.
assert.commandWorked(
primaryDB.createCollection(timeseriesCollName, {timeseries: {timeField: 'time'}}));
const timeseriesColl = primaryDB.getCollection(timeseriesCollName);
assert.commandWorked(timeseriesColl.insert({time: ISODate(), x: 1}));
// Used to wait for two-phase builds to complete.
let awaitIndex;
let awaitIndexTimeseries;
jsTest.log("Hanging index build on the primary node");
IndexBuildTest.pauseIndexBuilds(primary);
jsTest.log("Beginning index build");
awaitIndex = IndexBuildTest.startIndexBuild(primary, coll.getFullName(), {i: 1});
awaitIndexTimeseries =
IndexBuildTest.startIndexBuild(primary, timeseriesColl.getFullName(), {x: 1});
jsTest.log("Waiting for index build to start on secondary");
IndexBuildTest.waitForIndexBuildToStart(secondaryDB, collName, 'i_1');
IndexBuildTest.waitForIndexBuildToStart(
secondaryDB, TimeseriesTest.getBucketsCollName(timeseriesCollName), 'x_1');
jsTest.log("Adding a new node to the replica set");
let newNode = replSet.add({
// Disallow elections on secondary.
rsConfig: {
priority: 0,
votes: 0,
},
slowms: 30000, // Don't log slow operations on secondary.
});
// Ensure that the new node and primary cannot communicate to each other.
newNode.disconnect(primary);
replSet.reInitiate();
// Wait for the new node to finish initial sync.
waitForState(newNode, ReplSetTest.State.SECONDARY);
jsTest.log("Removing index build hang to allow it to finish");
IndexBuildTest.resumeIndexBuilds(primary);
awaitIndex();
awaitIndexTimeseries();
// Wait for the index builds to finish.
replSet.awaitReplication();
jsTest.log("Checking if the indexes match between the new node and the secondary node");
let newNodeDB = newNode.getDB(dbName);
jsTest.log("New nodes indexes:");
printjson(newNodeDB.getCollection(collName).getIndexes());
jsTest.log("Secondary nodes indexes:");
printjson(secondaryDB.getCollection(collName).getIndexes());
assert.eq(newNodeDB.getCollection(collName).getIndexes().length,
secondaryDB.getCollection(collName).getIndexes().length);
jsTest.log("New nodes indexes for time-series collection:");
printjson(newNodeDB.getCollection(timeseriesCollName).getIndexes());
jsTest.log("Secondary nodes indexes for time-series collection:");
printjson(secondaryDB.getCollection(timeseriesCollName).getIndexes());
assert.eq(newNodeDB.getCollection(timeseriesCollName).getIndexes().length,
secondaryDB.getCollection(timeseriesCollName).getIndexes().length);
replSet.stopSet();
})();