mirror of https://github.com/mongodb/mongo
134 lines
4.5 KiB
JavaScript
134 lines
4.5 KiB
JavaScript
/**
|
|
* Tests that retryable findAndModify data stored in the `config.image_collection` side collection
|
|
* do not get populated by nodes doing oplog application while in initial sync.
|
|
*
|
|
* This setParameter behavior does not yet exist on earlier versions.
|
|
* @tags: [multiversion_incompatible]
|
|
*/
|
|
(function() {
|
|
'use strict';
|
|
|
|
load('jstests/replsets/rslib.js');
|
|
|
|
// A secondary cannot compute retryable images during initial sync. Thus we skip db hash checks as
|
|
// its expected for config.image_collection to not match.
|
|
TestData.skipCheckDBHashes = true;
|
|
|
|
// Start a single node replica set.
|
|
const rst = new ReplSetTest({nodes: 1});
|
|
rst.startSet();
|
|
rst.initiateWithHighElectionTimeout();
|
|
|
|
const dbName = jsTest.name();
|
|
const primary = rst.getPrimary();
|
|
const primaryDB = primary.getDB(dbName);
|
|
const primaryColl = primaryDB['collection'];
|
|
|
|
primaryColl.insert({_id: 1});
|
|
|
|
let lsid = UUID();
|
|
jsTestLog({
|
|
"Pre-initial sync retryable findAndModify": assert.commandWorked(primaryDB.runCommand({
|
|
findandmodify: primaryColl.getName(),
|
|
lsid: {id: lsid},
|
|
txnNumber: NumberLong(1),
|
|
stmtId: NumberInt(1),
|
|
query: {_id: 1},
|
|
new: false,
|
|
update: {$set: {preInitialSync: true}}
|
|
}))
|
|
});
|
|
|
|
jsTestLog("Adding a new voting node (node1) to the replica set.");
|
|
const node1 = rst.add({
|
|
rsConfig: {priority: 1, votes: 1},
|
|
setParameter: {'failpoint.initialSyncHangAfterDataCloning': tojson({mode: 'alwaysOn'})}
|
|
});
|
|
rst.reInitiate();
|
|
|
|
jsTestLog("Wait for node1 to hang during initial sync.");
|
|
checkLog.containsJson(node1, 21184);
|
|
|
|
// Perform a findAndModify update that will not be retryable on the node that's concurrently initial
|
|
// syncing.
|
|
let result = assert.commandWorked(primaryDB.runCommand({
|
|
findandmodify: primaryColl.getName(),
|
|
lsid: {id: lsid},
|
|
txnNumber: NumberLong(2),
|
|
stmtId: NumberInt(1),
|
|
query: {_id: 1},
|
|
new: false,
|
|
update: {$set: {duringInitialSync: true}}
|
|
}));
|
|
jsTestLog({"Retryable findAndModify during initial sync": result});
|
|
|
|
// With a separate logical session, perform a findAndModify removal that will not be retryable on
|
|
// the node that's concurrently initial syncing.
|
|
let otherLsid = UUID();
|
|
jsTestLog({
|
|
"Retryable findAndModify removal during initial sync":
|
|
assert.commandWorked(primaryDB.runCommand({
|
|
findandmodify: primaryColl.getName(),
|
|
lsid: {id: otherLsid},
|
|
txnNumber: NumberLong(3),
|
|
stmtId: NumberInt(1),
|
|
query: {_id: 1},
|
|
new: false,
|
|
remove: true
|
|
}))
|
|
});
|
|
|
|
jsTestLog("Resuming initial sync.");
|
|
assert.commandWorked(
|
|
node1.adminCommand({configureFailPoint: "initialSyncHangAfterDataCloning", mode: 'off'}));
|
|
rst.waitForState(node1, ReplSetTest.State.SECONDARY);
|
|
|
|
let initialSyncedNode = rst.getSecondary();
|
|
rst.stepUp(initialSyncedNode);
|
|
|
|
result = assert.commandFailedWithCode(initialSyncedNode.getDB(dbName).runCommand({
|
|
findandmodify: primaryColl.getName(),
|
|
lsid: {id: lsid},
|
|
txnNumber: NumberLong(2),
|
|
stmtId: NumberInt(1),
|
|
query: {_id: 1},
|
|
new: false,
|
|
update: {$set: {duringInitialSync: true}}
|
|
}),
|
|
ErrorCodes.IncompleteTransactionHistory);
|
|
// Assert that retrying the update fails.
|
|
jsTestLog({
|
|
"Secondary": initialSyncedNode,
|
|
"Data": initialSyncedNode.getDB(dbName)['collection'].findOne(),
|
|
"Image": initialSyncedNode.getDB("config")['image_collection'].findOne({"_id.id": lsid}),
|
|
"retried findAndModify against synced node": result
|
|
});
|
|
|
|
result = assert.commandFailedWithCode(initialSyncedNode.getDB(dbName).runCommand({
|
|
findandmodify: primaryColl.getName(),
|
|
lsid: {id: otherLsid},
|
|
txnNumber: NumberLong(3),
|
|
stmtId: NumberInt(1),
|
|
query: {_id: 1},
|
|
new: false,
|
|
remove: true
|
|
}),
|
|
ErrorCodes.IncompleteTransactionHistory);
|
|
// Assert that retrying the delete fails.
|
|
jsTestLog({
|
|
"Secondary": initialSyncedNode,
|
|
"Data": initialSyncedNode.getDB(dbName)['collection'].findOne(),
|
|
"Image": initialSyncedNode.getDB("config")['image_collection'].findOne({"_id.id": otherLsid}),
|
|
"retried delete against synced node": result
|
|
});
|
|
|
|
// There should be two sessions/image entries on the initial syncing node, and both should be
|
|
// flagged as invalidated.
|
|
assert.eq(2, initialSyncedNode.getDB('config')['image_collection'].count({invalidated: true}));
|
|
assert.eq(2,
|
|
initialSyncedNode.getDB('config')['image_collection'].count(
|
|
{invalidatedReason: "initial sync"}));
|
|
|
|
rst.stopSet();
|
|
}());
|