jstests/replsets/tenant_migration_recipient_resume_on_stepup_and_restart.js
/**
 * Starts a migration and waits for it to commit, then runs the donorForgetMigration, and interrupts
 * the recipient using the 'interruptFunc', and asserts that the migration state is eventually
 * garbage collected.
 */
Starts a migration and waits for it to commit, then runs the donorForgetMigration, and interrupts
the recipient using the 'interruptFunc', and asserts that the migration state is eventually
garbage collected.
Starts a migration and waits for it to commit then runs the donorForgetMigration and interrupts the recipient using the ' interruptFunc ' and asserts that the migration state is eventually garbage collected .
function testRecipientForgetMigrationInterrupt(interruptFunc) {
    const donorRst = new ReplSetTest({
        nodes: 1,
        name: "donorRst",
        nodeOptions: Object.assign({}, migrationX509Options.donor, {
            setParameter: {
                tenantMigrationGarbageCollectionDelayMS: kGarbageCollectionDelayMS,
                ttlMonitorSleepSecs: kTTLMonitorSleepSecs,
            }
        })
    });
    const recipientRst = new ReplSetTest({
        nodes: 3,
        name: "recipientRst",
        nodeOptions: Object.assign({}, migrationX509Options.recipient, {
            setParameter: {
                tenantMigrationGarbageCollectionDelayMS: kGarbageCollectionDelayMS,
                ttlMonitorSleepSecs: kTTLMonitorSleepSecs,
            }
        })
    });
    donorRst.startSet();
    donorRst.initiate();
    recipientRst.startSet();
    recipientRst.initiate();
    const tenantMigrationTest =
        new TenantMigrationTest({name: jsTestName(), donorRst, recipientRst});
    const recipientPrimary = tenantMigrationTest.getRecipientPrimary();
    const migrationId = UUID();
    const migrationOpts = {
        migrationIdString: extractUUIDFromObject(migrationId),
        tenantId: kTenantId,
        recipientConnString: recipientRst.getURL(),
    };
    const donorRstArgs = TenantMigrationUtil.createRstArgs(donorRst);
    TenantMigrationTest.assertCommitted(
        tenantMigrationTest.runMigration(migrationOpts, {automaticForgetMigration: false}));
    const forgetMigrationThread = new Thread(TenantMigrationUtil.forgetMigrationAsync,
                                             migrationOpts.migrationIdString,
                                             donorRstArgs,
                                             false );
    forgetMigrationThread.start();
    assert.soon(() => {
        const res = assert.commandWorked(
            recipientPrimary.adminCommand({currentOp: true, desc: "tenant recipient migration"}));
        return res.inprog[0].expireAt != null;
    });
    sleep(Math.random() * kMaxSleepTimeMS);
    interruptFunc(recipientRst);
    assert.commandWorkedOrFailedWithCode(
        tenantMigrationTest.forgetMigration(migrationOpts.migrationIdString),
        ErrorCodes.NoSuchTenantMigration);
    assert.commandWorked(forgetMigrationThread.returnData());
    tenantMigrationTest.waitForMigrationGarbageCollection(migrationId, migrationOpts.tenantId);
    tenantMigrationTest.stop();
    donorRst.stopSet();
    recipientRst.stopSet();
}
function testRecipientForgetMigrationInterrupt ( interruptFunc ) { const donorRst = new ReplSetTest ( { nodes : 1 , name : "donorRst" , nodeOptions : Object . assign ( { } , migrationX509Options . donor , { setParameter : { tenantMigrationGarbageCollectionDelayMS : kGarbageCollectionDelayMS , ttlMonitorSleepSecs : kTTLMonitorSleepSecs , } } ) } ) ; const recipientRst = new ReplSetTest ( { nodes : 3 , name : "recipientRst" , nodeOptions : Object . assign ( { } , migrationX509Options . recipient , { setParameter : { tenantMigrationGarbageCollectionDelayMS : kGarbageCollectionDelayMS , ttlMonitorSleepSecs : kTTLMonitorSleepSecs , } } ) } ) ; donorRst . startSet ( ) ; donorRst . initiate ( ) ; recipientRst . startSet ( ) ; recipientRst . initiate ( ) ; const tenantMigrationTest = new TenantMigrationTest ( { name : jsTestName ( ) , donorRst , recipientRst } ) ; const recipientPrimary = tenantMigrationTest . getRecipientPrimary ( ) ; const migrationId = UUID ( ) ; const migrationOpts = { migrationIdString : extractUUIDFromObject ( migrationId ) , tenantId : kTenantId , recipientConnString : recipientRst . getURL ( ) , } ; const donorRstArgs = TenantMigrationUtil . createRstArgs ( donorRst ) ; TenantMigrationTest . assertCommitted ( tenantMigrationTest . runMigration ( migrationOpts , { automaticForgetMigration : false } ) ) ; const forgetMigrationThread = new Thread ( TenantMigrationUtil . forgetMigrationAsync , migrationOpts . migrationIdString , donorRstArgs , false ) ; forgetMigrationThread . start ( ) ; assert . soon ( ( ) => { const res = assert . commandWorked ( recipientPrimary . adminCommand ( { currentOp : true , desc : "tenant recipient migration" } ) ) ; return res . inprog [ 0 ] . expireAt != null ; } ) ; sleep ( Math . random ( ) * kMaxSleepTimeMS ) ; interruptFunc ( recipientRst ) ; assert . commandWorkedOrFailedWithCode ( tenantMigrationTest . forgetMigration ( migrationOpts . migrationIdString ) , ErrorCodes . NoSuchTenantMigration ) ; assert . commandWorked ( forgetMigrationThread . returnData ( ) ) ; tenantMigrationTest . waitForMigrationGarbageCollection ( migrationId , migrationOpts . tenantId ) ; tenantMigrationTest . stop ( ) ; donorRst . stopSet ( ) ; recipientRst . stopSet ( ) ; }
Starts a migration and waits for it to commit, then runs the donorForgetMigration, and interrupts
 the recipient using the 'interruptFunc', and asserts that the migration state is eventually
 garbage collected.
Starts a migration and waits for it to commit then runs the donorForgetMigration and interrupts the recipient using the ' interruptFunc ' and asserts that the migration state is eventually garbage collected .
/* retryOnRetryableErrors */ // Wait for recipientForgetMigration command to start.