mirror of https://github.com/mongodb/mongo
121 lines
4.7 KiB
JavaScript
121 lines
4.7 KiB
JavaScript
/**
|
|
* Tests recordIds show up when inserting into a collection with the
|
|
* 'recordIdsReplicated' flag set.
|
|
*
|
|
* @tags: [
|
|
* featureFlagRecordIdsReplicated,
|
|
* # TODO (SERVER-89640): Remove tag.
|
|
* # Incompatible with the recordIdsReplicated:true builder, as it sets the option
|
|
* # on all collections.
|
|
* exclude_when_record_ids_replicated
|
|
* ]
|
|
*/
|
|
import {
|
|
getRidForDoc,
|
|
validateShowRecordIdReplicatesAcrossNodes,
|
|
} from "jstests/libs/collection_write_path/replicated_record_ids_utils.js";
|
|
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
|
|
|
const replSet = new ReplSetTest({nodes: 2});
|
|
replSet.startSet();
|
|
replSet.initiate();
|
|
|
|
const primary = replSet.getPrimary();
|
|
const secondary = replSet.getSecondaries()[0];
|
|
|
|
const dbName = "test";
|
|
const unReplRidCollName = "unreplRecIdColl";
|
|
const replRidCollName = "replRecIdColl";
|
|
|
|
const primDB = primary.getDB(dbName);
|
|
const secDB = secondary.getDB(dbName);
|
|
|
|
const unReplRidNs = `${dbName}.${unReplRidCollName}`;
|
|
const replRidNs = `${dbName}.${replRidCollName}`;
|
|
|
|
const getOplogEntries = function (conn, oplogQuery) {
|
|
return replSet.findOplog(conn, oplogQuery).toArray();
|
|
};
|
|
|
|
const validateRidInOplogs = function (oplogQuery, expectedRid) {
|
|
const primOplogEntry = getOplogEntries(primary, oplogQuery)[0];
|
|
const secOplogEntry = getOplogEntries(secondary, oplogQuery)[0];
|
|
assert.eq(
|
|
primOplogEntry.rid,
|
|
expectedRid,
|
|
`Mismatching recordIds. Primary's oplog entry: ${tojson(primOplogEntry)}, on disk: ${tojson(
|
|
expectedRid,
|
|
)}. Oplog query ${tojson(oplogQuery)}`,
|
|
);
|
|
|
|
assert.eq(
|
|
secOplogEntry.rid,
|
|
expectedRid,
|
|
`Mismatching recordIds. Secondary's oplog entry: ${tojson(secOplogEntry)}, on disk: ${tojson(expectedRid)}`,
|
|
);
|
|
};
|
|
|
|
let docA = {"a": 1};
|
|
|
|
// Create a collection without the 'recordIdsReplicated' param set. This shouldn't
|
|
// insert the recordId (rid) into the oplog.
|
|
primDB[unReplRidCollName].insert(docA);
|
|
const oplogNoRid = replSet.findOplog(primary, {ns: `${unReplRidNs}`}).toArray()[0];
|
|
assert(!oplogNoRid.rid, `Unexpectedly found rid in entry: ${tojson(oplogNoRid)}`);
|
|
|
|
// Create a collection with the param set. This time the recordId should show up
|
|
// in the oplog.
|
|
primDB.runCommand({create: replRidCollName, recordIdsReplicated: true});
|
|
const docAInsertOpTime = assert.commandWorked(primDB.runCommand({insert: replRidCollName, documents: [docA]})).opTime;
|
|
replSet.awaitReplication();
|
|
const docAReplRid = getRidForDoc(primDB, replRidCollName, docA);
|
|
assert.eq(docAReplRid, getRidForDoc(secDB, replRidCollName, docA));
|
|
|
|
// For the replRecIdColl the recordId should be in the oplog, and should match
|
|
// the actual recordId on disk.
|
|
validateRidInOplogs({ns: `${replRidNs}`, ...docAInsertOpTime}, docAReplRid);
|
|
|
|
primDB.setLogLevel(3);
|
|
const newDocA = {
|
|
"a": 2,
|
|
};
|
|
const docAUpdateOpTime = assert.commandWorked(
|
|
primDB.runCommand({update: replRidCollName, updates: [{q: docA, u: {$set: {"a": 2}}}]}),
|
|
).opTime;
|
|
docA = newDocA;
|
|
replSet.awaitReplication();
|
|
validateRidInOplogs({ns: `${replRidNs}`, ...docAUpdateOpTime}, docAReplRid);
|
|
|
|
// The recordId should also be in the oplog entry for the delete.
|
|
const docARemoveOpTime = assert.commandWorked(
|
|
primDB.runCommand({delete: replRidCollName, deletes: [{q: docA, limit: 1}]}),
|
|
).opTime;
|
|
replSet.awaitReplication();
|
|
validateRidInOplogs({ns: `${replRidNs}`, ...docARemoveOpTime}, docAReplRid);
|
|
|
|
// On replication, secondaries apply oplog entries in parallel - a batch of oplog entries is
|
|
// distributed amongst several appliers, who apply the entries in parallel. Therefore, if we
|
|
// insert a single document at a time, it is likely that the replicated oplog batches will have
|
|
// just a single oplog entry each time, and therefore the secondary will basically be processing
|
|
// oplog entries in the same order that they appear on the primary. If processed in the same
|
|
// order, it is likely that the secondaries will generate the same recordIds as the primary,
|
|
// even with recordIdsReplicated:false.
|
|
//
|
|
// Therefore to ensure that recordIdsReplicated:true actually works we need to make sure that
|
|
// the appliers process oplog entries in parallel, and this is done by having a full batch of
|
|
// entries for the appliers to process. We can achieve this by performing an insertMany.
|
|
jsTestLog("Test inserting multiple documents at a time.");
|
|
|
|
const docs = [];
|
|
for (let i = 0; i < 500; i++) {
|
|
docs.push({_id: i});
|
|
}
|
|
assert.commandWorked(primDB[replRidCollName].insertMany(docs));
|
|
assert.eq(primDB[replRidCollName].count(), 500);
|
|
|
|
// Ensure that the on disk data on both nodes has the same recordIds.
|
|
replSet.awaitReplication();
|
|
validateShowRecordIdReplicatesAcrossNodes(replSet.nodes, dbName, replRidCollName);
|
|
|
|
replSet.stopSet();
|