86 lines
2.7 KiB
JavaScript
86 lines
2.7 KiB
JavaScript
/**
|
|
* Tests insert generating duplicate key during initial sync are skipped.
|
|
*
|
|
* @tags: [featureFlagRecordIdsReplicated]
|
|
*/
|
|
|
|
import {configureFailPoint} from "jstests/libs/fail_point_util.js";
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
|
import {waitForState} from "jstests/replsets/rslib.js";
|
|
|
|
const dbName = "test";
|
|
const collName = "testColl";
|
|
|
|
const rst = new ReplSetTest({
|
|
nodes: 1,
|
|
nodeOptions: {
|
|
setParameter: {
|
|
// On restart we will have no history to consult to figure out the highest leaf node.
|
|
minSnapshotHistoryWindowInSeconds: 0,
|
|
},
|
|
},
|
|
});
|
|
rst.startSet();
|
|
rst.initiate();
|
|
let primary = rst.getPrimary();
|
|
let primDB = primary.getDB(dbName);
|
|
|
|
assert.commandWorked(primDB.runCommand({insert: collName, documents: [{"_id": 1}]}));
|
|
|
|
jsTestLog("Add replica to the ReplSet");
|
|
// Add a node to the replica set and have it hang in the middle of initial sync.
|
|
const initialSyncNode = rst.add({
|
|
setParameter: {
|
|
"failpoint.initialSyncHangAfterGettingBeginApplyingTimestamp": tojson({mode: "alwaysOn"}),
|
|
},
|
|
});
|
|
|
|
const hangInitialSyncHangAfterGettingBeginApplyingTimestamp = configureFailPoint(
|
|
initialSyncNode,
|
|
"initialSyncHangAfterGettingBeginApplyingTimestamp",
|
|
);
|
|
|
|
jsTestLog("Waiting for new node to reach initial sync state");
|
|
rst.reInitiate();
|
|
rst.waitForState(initialSyncNode, ReplSetTest.State.STARTUP_2);
|
|
|
|
// Hang the initial sync node after it sets 'beginApplyingTimestamp' to ensure that the node will
|
|
// not set 'stopTimestamp' until after we perform the writes.
|
|
hangInitialSyncHangAfterGettingBeginApplyingTimestamp.wait();
|
|
|
|
jsTestLog("Inserting document into primary.");
|
|
assert.commandWorked(primDB.runCommand({insert: collName, documents: [{"_id": 2, "a": 2}]}));
|
|
|
|
jsTestLog("Updating document on primary.");
|
|
assert.commandWorked(
|
|
primDB.runCommand({
|
|
update: collName,
|
|
updates: [
|
|
{
|
|
q: {_id: 2},
|
|
u: {$set: {"a": 3}},
|
|
},
|
|
],
|
|
}),
|
|
);
|
|
|
|
// Set log level to debug so we log the skipped insert
|
|
const initialSyncNodeDB = initialSyncNode.getDB(dbName);
|
|
assert.commandWorked(initialSyncNodeDB.setLogLevel(3, "replication"));
|
|
|
|
jsTestLog("Allowing replica node to proceed with initial sync");
|
|
hangInitialSyncHangAfterGettingBeginApplyingTimestamp.off();
|
|
|
|
jsTestLog("Wait for replica node to reach SECONDARY state");
|
|
waitForState(initialSyncNode, ReplSetTest.State.SECONDARY);
|
|
rst.awaitReplication();
|
|
|
|
// Confirm we saw the skipped insert
|
|
checkLog.containsJson(initialSyncNode, 8776800);
|
|
|
|
jsTestLog("Validate new replica node");
|
|
const validateRes = assert.commandWorked(initialSyncNodeDB.runCommand({validate: collName}));
|
|
assert(validateRes.valid, "Validate failed on replica node: " + tojson(validateRes));
|
|
|
|
rst.stopSet();
|