Skip to content

Make doRollbackAndAssertForInitialState be more verbose #11

@pp0rtal

Description

@pp0rtal

Context

doRollbackAndAssertForInitialState can crash mysteriously for a validation error:

MongoBulkWriteError: Document failed validation
    at UnorderedBulkOperation.handleWriteError (node_modules/mongodb/src/bulk/common.ts:1207:9)
    at UnorderedBulkOperation.handleWriteError (node_modules/mongodb/src/bulk/unordered.ts:28:18)
    at resultHandler (node_modules/mongodb/src/bulk/common.ts:502:23)
    at /home/portal/Projects/platform/packages/backend/node_modules/mongodb/src/utils.ts:383:15
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
sample script
import { DataMigrationProcess } from "@backend/utils/env/load/script/datamigration";
import { DataMigration } from "../utils/DataMigration";
import type { ObjectId } from "mongodb";
import type { Path } from "@backend/utils/mongo/definitions";

const MIGRATION_ID = "migration_20231018T140000Z-removeDeletedUsersFromPathCoAuthors";

const processHandler = new DataMigrationProcess({ name: MIGRATION_ID }, buildMigration);
void processHandler.handleMigration();

export function buildMigration() {
    return new DataMigration<Path>({
        db: global._mongoClient.db(),
        id: MIGRATION_ID,
        collectionName: "paths",
        query: [
            {
                $match: {
                    coAuthors: { $exists: true, $not: { $size: 0 } }
                }
            },
            {
                $lookup: {
                    from: "users",
                    localField: "coAuthors",
                    foreignField: "_id",
                    as: "coAuthorsData"
                }
            },
            {
                $project: {
                    newCoAuthorIds: "$coAuthorsData._id"
                }
            }
        ],
        update
    });
}

async function update({ newCoAuthorIds }: { newCoAuthorIds: ObjectId[] }) {
    return { $set: { coAuthors: newCoAuthorIds } };
}
sample test file
import { ObjectId } from "mongodb";
import _ from "lodash";
import { expect, generators } from "@backend/test/integrationTest";
import { doRollbackAndAssertForInitialState } from "../utils/testUtils";
import { buildMigration } from "./20231018T140000Z-removeDeletedUsersFromPathCoAuthors.unified";
import type { Path } from "@backend/utils/mongo/definitions";
import type { DataMigration } from "../utils/DataMigration";

describe("migration_20231018T140000Z-removeDeletedUsersFromPathCoAuthors", () => {
    let dataMigration: DataMigration<Path>;

    beforeEach(async () => {
        dataMigration = buildMigration();
    });

    it("should remove deleted userId from coAuthors", async () => {
        const user = await generators.generateUser();
        const path = await generators.paths.generatePath({ coAuthors: [user._id, new ObjectId()] });

        await dataMigration.update();

        const updatedPath = await _db.paths.findIt(path._id);
        expect(updatedPath).to.deep.equal({
            ...path,
            coAuthors: [user._id]
        });
        await doRollbackAndAssertForInitialState(dataMigration, [path]);
    });
});

Todo

  • Make it log clearly error occured in doRollbackAndAssertForInitialState (try catch)
  • Optionally log document before / after

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions