jstests/replsets/tenant_migration_donor_rollback_recovery.js
/**
 * Runs donorForgetMigration after completing a migration. Waits for the donor's primary to
 * mark the donor's state doc as garbage collectable, then forces the write to be rolled back.
 * After the replication steady state is reached, asserts that donorForgetMigration can be retried
 * on the new primary and that the state doc is eventually garbage collected.
 */
Runs donorForgetMigration after completing a migration. Waits for the donor's primary to
mark the donor's state doc as garbage collectable, then forces the write to be rolled back.
After the replication steady state is reached, asserts that donorForgetMigration can be retried
on the new primary and that the state doc is eventually garbage collected.
Runs donorForgetMigration after completing a migration . Waits for the donor ' s primary to mark the donor ' s state doc as garbage collectable then forces the write to be rolled back . After the replication steady state is reached asserts that donorForgetMigration can be retried on the new primary and that the state doc is eventually garbage collected .
function testRollBackMarkingStateGarbageCollectable() {
    const migrationId = UUID();
    const migrationOpts = makeMigrationOpts(migrationId, kTenantId + "-markGarbageCollectable");
    let forgetMigrationThread;
    let setUpFunc = (tenantMigrationTest, donorRstArgs) => {
        TenantMigrationTest.assertCommitted(tenantMigrationTest.runMigration(
            migrationOpts, {retryOnRetryableErrors: true, automaticForgetMigration: false}));
    };
    let rollbackOpsFunc = (tenantMigrationTest, donorRstArgs) => {
        const donorPrimary = tenantMigrationTest.getDonorPrimary();
        forgetMigrationThread = new Thread(TenantMigrationUtil.forgetMigrationAsync,
                                           migrationOpts.migrationIdString,
                                           donorRstArgs,
                                           true );
        forgetMigrationThread.start();
        assert.soon(() => {
            let docs =
                donorPrimary.getCollection(TenantMigrationTest.kConfigDonorsNS).find().toArray();
             1) It has an `expireAt`.
             2) The document is deleted/the collection is empty.
            return 1 === donorPrimary.getCollection(TenantMigrationTest.kConfigDonorsNS).count({
                _id: migrationId,
                expireAt: {$exists: 1}
            }) ||
                donorPrimary.getCollection(TenantMigrationTest.kConfigDonorsNS).count({
                    _id: migrationId
                }) === 0;
        });
    };
    let steadyStateFunc = (tenantMigrationTest) => {
         Verify that the migration state got garbage collected successfully despite the rollback.
        assert.commandWorked(forgetMigrationThread.returnData());
        tenantMigrationTest.waitForMigrationGarbageCollection(migrationId, migrationOpts.tenantId);
    };
    testRollBack(setUpFunc, rollbackOpsFunc, steadyStateFunc);
}
function testRollBackMarkingStateGarbageCollectable ( ) { const migrationId = UUID ( ) ; const migrationOpts = makeMigrationOpts ( migrationId , kTenantId + "-markGarbageCollectable" ) ; let forgetMigrationThread ; let setUpFunc = ( tenantMigrationTest , donorRstArgs ) => { TenantMigrationTest . assertCommitted ( tenantMigrationTest . runMigration ( migrationOpts , { retryOnRetryableErrors : true , automaticForgetMigration : false } ) ) ; } ; let rollbackOpsFunc = ( tenantMigrationTest , donorRstArgs ) => { const donorPrimary = tenantMigrationTest . getDonorPrimary ( ) ; forgetMigrationThread = new Thread ( TenantMigrationUtil . forgetMigrationAsync , migrationOpts . migrationIdString , donorRstArgs , true ) ; forgetMigrationThread . start ( ) ; assert . soon ( ( ) => { let docs = donorPrimary . getCollection ( TenantMigrationTest . kConfigDonorsNS ) . find ( ) . toArray ( ) ; return 1 === donorPrimary . getCollection ( TenantMigrationTest . kConfigDonorsNS ) . count ( { _id : migrationId , expireAt : { $exists : 1 } } ) || donorPrimary . getCollection ( TenantMigrationTest . kConfigDonorsNS ) . count ( { _id : migrationId } ) === 0 ; } ) ; } ; let steadyStateFunc = ( tenantMigrationTest ) => { assert . commandWorked ( forgetMigrationThread . returnData ( ) ) ; tenantMigrationTest . waitForMigrationGarbageCollection ( migrationId , migrationOpts . tenantId ) ; } ; testRollBack ( setUpFunc , rollbackOpsFunc , steadyStateFunc ) ; }
Runs donorForgetMigration after completing a migration.
Runs donorForgetMigration after completing a migration .
// Run donorForgetMigration and wait for the primary to do the write to mark the state doc // as garbage collectable. /* retryOnRetryableErrors */ // There is a ttl index on `expireAt`. Thus we know the state doc is marked as garbage // collectible either when: // // 1) It has an `expireAt`. // 2) The document is deleted/the collection is empty. // Verify that the migration state got garbage collected successfully despite the rollback.