Files
mongo/jstests/replsets/dbcheck/dbcheck_consistent_batch_health_log.js
Brad Cater 24544088c7 SERVER-103992 Put dbcheck in its own subdir. (#35229)
GitOrigin-RevId: 145fc4403e4871e38e2c7377a507a182adf3e51c
2025-04-25 13:39:05 +00:00

107 lines
4.0 KiB
JavaScript

/**
* Tests dbCheck health log entries are consistent for all nodes in the replica sets.
*
* @tags: [
* requires_fcv_80
* ]
*/
import {ReplSetTest} from "jstests/libs/replsettest.js";
import {checkHealthLog, resetAndInsert, runDbCheck} from "jstests/replsets/libs/dbcheck_utils.js";
const nDocs = 10;
const dbCheckHealthLogEveryNBatches = 4;
// We are going to force 1 doc per batch.
const numBatchLogExpected = Math.floor(nDocs / dbCheckHealthLogEveryNBatches);
const maxBatchTimeMillis = 10;
const replSet = new ReplSetTest({
name: jsTestName(),
nodes: 2,
nodeOptions: {setParameter: {dbCheckHealthLogEveryNBatches: dbCheckHealthLogEveryNBatches}},
});
replSet.startSet();
replSet.initiate();
const dbName = "dbCheckConsistentHealthLog";
const collName = "collName";
const primary = replSet.getPrimary();
const secondary = replSet.getSecondary();
const primaryHealthlog = primary.getDB("local").system.healthlog;
const secondaryHealthlog = secondary.getDB("local").system.healthlog;
const db = primary.getDB(dbName);
const secondarydb = secondary.getDB(dbName);
// Only run this test for debug=off, because we log all batches in debug builds.
const debugBuild =
db.adminCommand("buildInfo").debug || secondarydb.adminCommand("buildInfo").debug;
if (debugBuild) {
jsTestLog("Skipping the test because debug is on.");
replSet.stopSet();
quit();
}
function healthLogConsistent(params) {
jsTestLog("Clear healthLog and run dbcheck and waits for it to finish.");
resetAndInsert(replSet, db, collName, nDocs);
assert.commandWorked(db.runCommand({
createIndexes: collName,
indexes: [{key: {a: 1}, name: 'a_1'}],
}));
replSet.awaitReplication();
runDbCheck(replSet,
db,
collName,
{...params, maxDocsPerBatch: 1, maxBatchTimeMillis: maxBatchTimeMillis},
true /* awaitCompletion */);
const collUUID = db.getCollectionInfos({name: collName})[0].info.uuid;
let query = {operation: "dbCheckBatch", collectionUUID: collUUID};
checkHealthLog(primaryHealthlog, query, numBatchLogExpected);
checkHealthLog(secondaryHealthlog, query, numBatchLogExpected);
jsTestLog("Testing that 'data.batchId' field exist in batch health logs.");
// There are no dbCheckBatch health log entries without a batchId.
query = {operation: "dbCheckBatch", "data.batchId": {$exists: false}};
checkHealthLog(primaryHealthlog, query, 0);
checkHealthLog(secondaryHealthlog, query, 0);
let primaryHealthLogs =
primaryHealthlog.find({operation: "dbCheckBatch"}).toArray().reduce((map, log) => {
map[log.data.batchId] = log.data;
return map;
}, {});
let secondaryHealthLogs =
secondaryHealthlog.find({operation: "dbCheckBatch"}).toArray().reduce((map, log) => {
map[log.data.batchId] = log.data;
return map;
}, {});
jsTestLog(`Verifying that batch healthlog entries should be the same across nodes. Params: ${
tojson(params)}`);
jsTestLog(`Primary health log: ${tojson(primaryHealthLogs)}`);
assert.eq(tojson(primaryHealthLogs),
tojson(secondaryHealthLogs),
`primary health logs: ${tojson(primaryHealthLogs)}, secondary health logs: ${
tojson(secondaryHealthLogs)}`);
}
// Running the dbcheck multiple times should invalidate all the in-memory states between primary
// and secondaries. That should be false if the secondaries is keeping a global number of
// batches while the primary keeps a local number for each dbcheck run because (NumberOfBatches
// % dbCheckHealthLogEveryNBatches (10 % 4)) != 0.
const validateModes = [
{},
{validateMode: "dataConsistency"},
{validateMode: "dataConsistencyAndMissingIndexKeysCheck"},
{validateMode: "extraIndexKeysCheck", secondaryIndex: "a_1"}
];
for (let i = 0; i < 3; i++) {
for (let params of validateModes) {
jsTestLog(`Running test with parameters ${tojson(params)} and iteration ${i}`);
healthLogConsistent(params);
}
}
replSet.stopSet();