Files
mongo/jstests/replsets/dbcheck/dbcheck_consistent_batch_health_log.js
Zac 591928c619 SERVER-108478 JS formatted by prettier and remove clang-format (#39656)
GitOrigin-RevId: 6c8f6aded47f260aa4f7c231b17dae3302cb1e04
2025-08-21 17:27:09 +00:00

114 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();