/**
 * Ensure that a stepdown of the primary kills any TTLMonitor clients, but not the TTLMonitor
 * thread itself and after stepdown finishes, the TTLMonitor resumes.
 *
 * @tags: [requires_replication]
 */
(function() {
"use strict";

load("jstests/libs/fail_point_util.js");

const dbName = "kill_ttl_on_stepdown";

const rst = new ReplSetTest({
    nodes: [{}, {rsConfig: {priority: 0}}],
    nodeOptions: {setParameter: "ttlMonitorSleepSecs=15"}
});
rst.startSet();
rst.initiate();

let primary = rst.getPrimary();
let db = primary.getDB(dbName);

// Create a TTL index.
db.getCollection("test").createIndex({x: 1}, {expireAfterSeconds: 3600});

function getNumTTLPasses() {
    let serverStatus = assert.commandWorked(primary.adminCommand({serverStatus: 1}));
    return serverStatus.metrics.ttl.passes;
}

// Let the TTLMonitor do some passes.
assert.soon(() => {
    return getNumTTLPasses() > 0;
}, "TTLMonitor never did any passes.");

let failPoint = configureFailPoint(primary, "hangTTLMonitorWithLock");
failPoint.wait();

// See how many passes the TTLMonitor has done, before we stepdown the primary, killing it.
let ttlPassesBeforeStepdown = getNumTTLPasses();

// Force a stepdown of the primary.
assert.commandWorked(
    primary.getDB("admin").runCommand({replSetStepDown: 60 * 10 /* 10 minutes */, force: true}));
rst.waitForState(primary, ReplSetTest.State.SECONDARY);
assert.commandWorked(primary.adminCommand({replSetFreeze: 0}));
assert.commandWorked(primary.adminCommand({replSetStepUp: 1}));

primary = rst.getPrimary();

// Ensure the TTLMonitor was interrupted.
checkLog.contains(primary, "TTLMonitor was interrupted");

// Disable the failpoint on the node that stepped down.
failPoint.off();

// Wait until the number TTLMonitor passes increases, informing us that the TTLMonitor thread
// was not killed entirely and will continue to run after stepdown finishes.
assert.soon(() => {
    if (getNumTTLPasses() > ttlPassesBeforeStepdown) {
        return true;
    }
}, "TTLMonitor was not running after stepdown");

rst.stopSet();
}());
