jstests/replsets/tenant_migration_donor_resume_on_stepup_and_restart.js
/**
 * Starts a migration and sets the passed in failpoint, then runs the donorAbortMigration, and
 * interrupts the donor using the 'interruptFunc', and asserts that the migration state is
 * eventually garbage collected.
 */
Starts a migration and sets the passed in failpoint, then runs the donorAbortMigration, and
interrupts the donor using the 'interruptFunc', and asserts that the migration state is
eventually garbage collected.
Starts a migration and sets the passed in failpoint then runs the donorAbortMigration and interrupts the donor using the ' interruptFunc ' and asserts that the migration state is eventually garbage collected .
function testDonorAbortMigrationInterrupt(interruptFunc, fpName, isShutdown = false) {
    const donorRst = new ReplSetTest({
        nodes: 3,
        name: "donorRst",
        nodeOptions: Object.assign({}, migrationX509Options.donor, {
            setParameter: {
                tenantMigrationGarbageCollectionDelayMS: kGarbageCollectionDelayMS,
                ttlMonitorSleepSecs: kTTLMonitorSleepSecs,
            }
        })
    });
    const recipientRst = new ReplSetTest({
        nodes: 1,
        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 migrationId = UUID();
    const migrationOpts = {
        migrationIdString: extractUUIDFromObject(migrationId),
        tenantId: kTenantId,
        recipientConnString: recipientRst.getURL(),
    };
    const donorRstArgs = TenantMigrationUtil.createRstArgs(donorRst);
    let donorPrimary = tenantMigrationTest.getDonorPrimary();
    let fp;
    if (fpName) {
        fp = configureFailPoint(donorPrimary, fpName);
    }
    assert.commandWorked(tenantMigrationTest.startMigration(migrationOpts));
    const tryAbortThread = new Thread(TenantMigrationUtil.tryAbortMigrationAsync,
                                      {migrationIdString: migrationOpts.migrationIdString},
                                      donorRstArgs,
                                      true );
    tryAbortThread.start();
    assert.soon(() => {
        const res = assert.commandWorked(
            donorPrimary.adminCommand({currentOp: true, desc: "tenant donor migration"}));
        return res.inprog[0].receivedCancellation;
    });
    interruptFunc(donorRst);
    if (fp && !isShutdown) {
        fp.off();
    }
    tryAbortThread.join();
    let res = tryAbortThread.returnData();
    assert.commandWorkedOrFailedWithCode(res, ErrorCodes.TenantMigrationCommitted);
    donorPrimary = tenantMigrationTest.getDonorPrimary();
    let configDonorsColl = donorPrimary.getCollection(TenantMigrationTest.kConfigDonorsNS);
    let donorDoc = configDonorsColl.findOne({tenantId: kTenantId});
    if (!res.ok) {
        assert.eq(donorDoc.state, TenantMigrationTest.DonorState.kCommitted);
    } else {
        assert.eq(donorDoc.state, TenantMigrationTest.DonorState.kAborted);
    }
    tenantMigrationTest.stop();
    donorRst.stopSet();
    recipientRst.stopSet();
}
function testDonorAbortMigrationInterrupt ( interruptFunc , fpName , isShutdown = false ) { const donorRst = new ReplSetTest ( { nodes : 3 , name : "donorRst" , nodeOptions : Object . assign ( { } , migrationX509Options . donor , { setParameter : { tenantMigrationGarbageCollectionDelayMS : kGarbageCollectionDelayMS , ttlMonitorSleepSecs : kTTLMonitorSleepSecs , } } ) } ) ; const recipientRst = new ReplSetTest ( { nodes : 1 , 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 migrationId = UUID ( ) ; const migrationOpts = { migrationIdString : extractUUIDFromObject ( migrationId ) , tenantId : kTenantId , recipientConnString : recipientRst . getURL ( ) , } ; const donorRstArgs = TenantMigrationUtil . createRstArgs ( donorRst ) ; let donorPrimary = tenantMigrationTest . getDonorPrimary ( ) ; let fp ; if ( fpName ) { fp = configureFailPoint ( donorPrimary , fpName ) ; } assert . commandWorked ( tenantMigrationTest . startMigration ( migrationOpts ) ) ; const tryAbortThread = new Thread ( TenantMigrationUtil . tryAbortMigrationAsync , { migrationIdString : migrationOpts . migrationIdString } , donorRstArgs , true ) ; tryAbortThread . start ( ) ; assert . soon ( ( ) => { const res = assert . commandWorked ( donorPrimary . adminCommand ( { currentOp : true , desc : "tenant donor migration" } ) ) ; return res . inprog [ 0 ] . receivedCancellation ; } ) ; interruptFunc ( donorRst ) ; if ( fp && ! isShutdown ) { fp . off ( ) ; } tryAbortThread . join ( ) ; let res = tryAbortThread . returnData ( ) ; assert . commandWorkedOrFailedWithCode ( res , ErrorCodes . TenantMigrationCommitted ) ; donorPrimary = tenantMigrationTest . getDonorPrimary ( ) ; let configDonorsColl = donorPrimary . getCollection ( TenantMigrationTest . kConfigDonorsNS ) ; let donorDoc = configDonorsColl . findOne ( { tenantId : kTenantId } ) ; if ( ! res . ok ) { assert . eq ( donorDoc . state , TenantMigrationTest . DonorState . kCommitted ) ; } else { assert . eq ( donorDoc . state , TenantMigrationTest . DonorState . kAborted ) ; } tenantMigrationTest . stop ( ) ; donorRst . stopSet ( ) ; recipientRst . stopSet ( ) ; }
Starts a migration and sets the passed in failpoint, then runs the donorAbortMigration, and
 interrupts the donor using the 'interruptFunc', and asserts that the migration state is
 eventually garbage collected.
Starts a migration and sets the passed in failpoint then runs the donorAbortMigration and interrupts the donor using the ' interruptFunc ' and asserts that the migration state is eventually garbage collected .
// If we passed in a valid failpoint we set it, otherwise we let the migration run normally. /* retryOnRetryableErrors */ // Wait for donorAbortMigration command to start. // Turn off failpoint in order to allow the migration to resume after stepup.