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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions