0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-24 16:46:00 +01:00
mongodb/jstests/replsets/election_participant_new_term_metrics.js
Moustafa Maher 2fd5f78d5a SERVER-95421 make initiateWithHighElectionTimeout the default in ReplSetTest (#28174)
GitOrigin-RevId: df168ee363c3f0e86526270437d3688ac4bb326d
2024-10-22 02:53:25 +00:00

105 lines
5.5 KiB
JavaScript

/**
* This test checks that the 'newTermStartDate' and 'newTermAppliedDate' metrics in
* 'electionParticipantMetrics' are set and updated correctly. We test this with a three node
* replica set by successfully stepping up one of the secondaries, then failing to step up the
* original primary. We check that the metrics are appropriately set or unset after each election.
*/
import {ReplSetTest} from "jstests/libs/replsettest.js";
const testName = jsTestName();
const rst = new ReplSetTest({name: testName, nodes: [{}, {}, {rsConfig: {priority: 0}}]});
rst.startSet();
// Make sure there are no election timeouts firing for the duration of the test. This helps
// ensure that the test will only pass if the election succeeds.
rst.initiate();
const originalPrimary = rst.getPrimary();
const newPrimary = rst.getSecondaries()[0];
const testNode = rst.getSecondaries()[1];
// Set up a failpoint that forces the original primary to vote no in this election. This guarantees
// that 'testNode' will be a participant in this election, since its vote will be needed for the new
// primary to win.
assert.commandWorked(
originalPrimary.adminCommand({configureFailPoint: "voteNoInElection", mode: "alwaysOn"}));
// Step up the new primary.
rst.stepUp(newPrimary);
// Since the new term oplog entry needs to be replicated onto testNode for the metrics to be set, we
// must await replication before checking the metrics.
rst.awaitReplication();
let testNodeReplSetGetStatus = assert.commandWorked(testNode.adminCommand({replSetGetStatus: 1}));
let testNodeElectionParticipantMetrics = testNodeReplSetGetStatus.electionParticipantMetrics;
const originalNewTermStartDate = testNodeElectionParticipantMetrics.newTermStartDate;
const originalNewTermAppliedDate = testNodeElectionParticipantMetrics.newTermAppliedDate;
// These fields should be set, since testNode has received and applied the new term oplog entry
// after the election.
assert(originalNewTermStartDate,
() => "Response should have an 'electionParticipantMetrics.newTermStartDate' field: " +
tojson(testNodeElectionParticipantMetrics));
assert(originalNewTermAppliedDate,
() => "Response should have an 'electionParticipantMetrics.newTermAppliedDate' field: " +
tojson(testNodeElectionParticipantMetrics));
// Set up a failpoint that forces newPrimary and testNode to vote no in the election, in addition to
// the new primary above. This will cause the dry run to fail for the original primary.
assert.commandWorked(
newPrimary.adminCommand({configureFailPoint: "voteNoInElection", mode: "alwaysOn"}));
assert.commandWorked(
testNode.adminCommand({configureFailPoint: "voteNoInElection", mode: "alwaysOn"}));
// Attempt to step up the original primary.
assert.commandFailedWithCode(originalPrimary.adminCommand({replSetStepUp: 1}),
ErrorCodes.CommandFailed);
testNodeReplSetGetStatus = assert.commandWorked(testNode.adminCommand({replSetGetStatus: 1}));
testNodeElectionParticipantMetrics = testNodeReplSetGetStatus.electionParticipantMetrics;
// The 'newTermStartDate' and 'newTermAppliedDate' fields should not be cleared, since the term is
// not incremented when a dry run election is initiated.
assert(testNodeElectionParticipantMetrics.newTermStartDate,
() => "Response should have an 'electionParticipantMetrics.newTermStartDate' field: " +
tojson(testNodeElectionParticipantMetrics));
assert(testNodeElectionParticipantMetrics.newTermAppliedDate,
() => "Response should have an 'electionParticipantMetrics.newTermAppliedDate' field: " +
tojson(testNodeElectionParticipantMetrics));
// The fields should store the same dates, since a new term oplog entry was not received.
assert.eq(originalNewTermStartDate, testNodeElectionParticipantMetrics.newTermStartDate);
assert.eq(originalNewTermAppliedDate, testNodeElectionParticipantMetrics.newTermAppliedDate);
// Clear the previous failpoint and set up a new one that forces the two current secondaries to vote
// yes for the candidate in the dry run election and no in the real election. This will cause the
// real election to fail.
assert.commandWorked(
newPrimary.adminCommand({configureFailPoint: "voteNoInElection", mode: "off"}));
assert.commandWorked(newPrimary.adminCommand(
{configureFailPoint: "voteYesInDryRunButNoInRealElection", mode: "alwaysOn"}));
assert.commandWorked(testNode.adminCommand({configureFailPoint: "voteNoInElection", mode: "off"}));
assert.commandWorked(testNode.adminCommand(
{configureFailPoint: "voteYesInDryRunButNoInRealElection", mode: "alwaysOn"}));
// Attempt to step up the original primary.
assert.commandFailedWithCode(originalPrimary.adminCommand({replSetStepUp: 1}),
ErrorCodes.CommandFailed);
testNodeReplSetGetStatus = assert.commandWorked(testNode.adminCommand({replSetGetStatus: 1}));
testNodeElectionParticipantMetrics = testNodeReplSetGetStatus.electionParticipantMetrics;
// Since the election succeeded in the dry run, a new term was encountered by the secondary.
// However, because the real election failed, there was no new term oplog entry, so these fields
// should not be set.
assert(!testNodeElectionParticipantMetrics.newTermStartDate,
() => "Response should not have an 'electionParticipantMetrics.newTermStartDate' field: " +
tojson(testNodeElectionParticipantMetrics));
assert(!testNodeElectionParticipantMetrics.newTermAppliedDate,
() => "Response should not have an 'electionParticipantMetrics.newTermAppliedDate' field: " +
tojson(testNodeElectionParticipantMetrics));
rst.stopSet();