0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-24 00:17:37 +01:00
mongodb/jstests/serverless/initial_sync_change_collection.js
Matt Broadstone 771dabd098 SERVER-81339 Convert ReplSetTest and ShardingTest to modules (#26332)
GitOrigin-RevId: 744aa110a53786b23c62ff53f87a1418b5991e8d
2024-08-20 22:00:49 +00:00

111 lines
4.8 KiB
JavaScript

// Tests that the data cloning phase of initial sync does not clone the change collection documents
// and when the initial sync has completed the change collection and oplog entries are exactly same
// in the new secondary.
// @tags: [
// requires_fcv_62,
// ]
//
import {kDefaultWaitForFailPointTimeout} from "jstests/libs/fail_point_util.js";
import {ReplSetTest} from "jstests/libs/replsettest.js";
import {
ChangeStreamMultitenantReplicaSetTest,
verifyChangeCollectionEntries
} from "jstests/serverless/libs/change_collection_util.js";
const replSetTest = new ChangeStreamMultitenantReplicaSetTest({nodes: 1});
const primary = replSetTest.getPrimary();
// User id and the associated tenant id.
const userInfo = {
tenantId: ObjectId(),
user: ObjectId().str
};
// Create a connection to the primary node for the tenant.
const tenantPrimaryNode = ChangeStreamMultitenantReplicaSetTest.getTenantConnection(
primary.host, userInfo.tenantId, userInfo.user);
// Enable the change stream for the tenant.
replSetTest.setChangeStreamState(tenantPrimaryNode, true);
// Get the change collection on the primary node for the tenant.
const primaryChangeColl = tenantPrimaryNode.getDB("config").system.change_collection;
const mdbStockPriceDoc = {
_id: "mdb",
price: 250
};
// The document 'mdbStockPriceDoc' is inserted before starting the initial sync. As such the
// document 'mdbStockPriceDoc' should not be cloned in the secondary after initial sync is complete.
assert.commandWorked(tenantPrimaryNode.getDB("test").stockPrice.insert(mdbStockPriceDoc));
assert.eq(primaryChangeColl.find({o: mdbStockPriceDoc}).toArray().length, 1);
// Add a new secondary to the replica set and block the initial sync after the data cloning is done.
const secondary = replSetTest.add({
setParameter: {
// Hang after the data cloning phase is completed.
"failpoint.initialSyncHangAfterDataCloning": tojson({mode: "alwaysOn"})
}
});
replSetTest.reInitiate();
// Wait for the cloning phase to complete. The cloning phase should not clone documents of the
// change collection from the primary.
assert.commandWorked(secondary.adminCommand({
waitForFailPoint: "initialSyncHangAfterDataCloning",
timesEntered: 1,
maxTimeMS: kDefaultWaitForFailPointTimeout
}));
const tslaStockPriceDoc = {
_id: "tsla",
price: 650
};
// The document 'tslaStockPriceDoc' is inserted in the primary after the data cloning phase has
// completed, as such this should be inserted in the secondary's change change collection.
assert.commandWorked(tenantPrimaryNode.getDB("test").stockPrice.insert(tslaStockPriceDoc));
assert.eq(primaryChangeColl.find({o: tslaStockPriceDoc}).toArray().length, 1);
// Unblock the initial sync process.
assert.commandWorked(secondary.getDB("test").adminCommand(
{configureFailPoint: "initialSyncHangAfterDataCloning", mode: "off"}));
// Wait for the initial sync to complete.
replSetTest.waitForState(secondary, ReplSetTest.State.SECONDARY);
// Create a connection to the secondary node for the tenant.
const tenantSecondaryNode = ChangeStreamMultitenantReplicaSetTest.getTenantConnection(
secondary.host, userInfo.tenantId, userInfo.user);
// Verify that the document 'mdbStockPriceDoc' does not exist and the document 'tslaStockPriceDoc'
// exists in the secondary's change collection.
const changeCollDocs =
tenantSecondaryNode.getDB("config")
.system.change_collection.find({$or: [{o: mdbStockPriceDoc}, {o: tslaStockPriceDoc}]})
.toArray();
assert.eq(changeCollDocs.length, 1);
assert.eq(changeCollDocs[0].o, tslaStockPriceDoc);
// Get the timestamp of the first and the last entry from the secondary's oplog.
const oplogDocs = secondary.getDB("local").oplog.rs.find().toArray();
assert.gt(oplogDocs.length, 0);
const startOplogTimestamp = oplogDocs[0].ts;
const endOplogTimestamp = oplogDocs.at(-1).ts;
// The change collection gets created at the data cloning phase and documents are written to the
// oplog only after the data cloning is done. And so, the change collection already exists in place
// to capture oplog entries. As such, the change collection entries and the oplog entries for
// timestamp range ('startOplogTimestamp', 'endOplogTimestamp'] must be the same.
verifyChangeCollectionEntries(secondary,
startOplogTimestamp,
endOplogTimestamp,
userInfo.tenantId,
_createTenantToken({tenant: userInfo.tenantId}));
// The state of the change collection after the initial sync is not consistent with the primary.
// This is because the change collection's data is never cloned to the secondary, only it's creation
// is cloned. As such, we will skip the db hash check on the change collection.
replSetTest.stopSet(undefined /* signal */, undefined /* forRestart */, {skipCheckDBHashes: true});