Search code examples
node.jsmongodbmongoosegraphql

Final argument to `executeLegacyOperation` must be a callback


Not sure to describe the issue but we are trying to upgrade to mongoDB 5.0 and have updated mongoose to 6.0.12 in the process of upgrading mongoDB. In running the batch tests (jest), we are stuck on the error message "Final argument to executeLegacyOperation must be a callback"

The entire message is :

Failed: Array [
      GraphQLError {
        "locations": Array [
          [Object],
        ],
        "message": "Final argument to `executeLegacyOperation` must be a callback",
        "path": Array [
          "upsertBatchRole",
        ],
      },
    ]

An example of a test that is failing:

        test('should update existing items and return UPDATED status', async () => {
            const {
                data: { upsertBatchRole },
            } = await gqlClient.fetch<{ upsertBatchRole: GQLUpsertBatchRoleOutput }>(upsertBatchRoleMutation, {
                condition: {},
                input: [
                    {
                        name: 'new',
                        id: '57',
                    },
                ],
            });

            expect(upsertBatchRole).not.toBeNull();
            const { status, data } = upsertBatchRole as GQLUpsertBatchRoleOutput;

            const unitedData = uniteCategorizedArrays<GQLRole>({ ...data });

            expect(status).toBe(ms.UPDATED);
            expect(unitedData.length).toBe(1);
            expect(unitedData[0]).toHaveProperty('name');
            expect(unitedData[0]?.name).toBe('new');
            _.forEach(unitedData, (item) => {
                expect(item).toHaveProperty('id');
                expect(item).toHaveProperty('name');
            });

            const {
                data: { roleList },
            } = await gqlClient.fetch(`
                roleList {
                    name
                }
            `);
            const orderedList = _.sortBy(roleList, 'name');
            expect(orderedList).toHaveLength(1);
            expect(orderedList[0].name).toBe('new');
        });

Currently, graphql is at 15.5.1. Tried to upgrade graphql and got as far as 15.8.0 as higher versions produced a different error. Current node version is 14.21.3

Not sure if graphql is the issue here so looking for any ideas on how to resolve the above issue.

UPDATED

Here is a code snippet from upsertBatchEntity.js:

async function updateBatchEntity(Collection, entitiesToUpdate, gqlInfo) {
    if (_.isEmpty(entitiesToUpdate)) return { status: ms.UPDATED, data: [] };

    const transactionSession = getCurrentTransactionSessionFromGQLInfo(gqlInfo);

    const bulkUpdate = Collection.collection.initializeOrderedBulkOp({
        session: transactionSession,
    });

    _.forEach(entitiesToUpdate, (entity) => {
        const _id = new mongoose.Types.ObjectId(entity._id);
        const entityProperties = _.omit(entity, ['id', '_id']);

        const convertedEntityProperties = convertEntityPropertiesToObjectIdWhereNeeded(Collection, entityProperties);

        bulkUpdate.find({ _id }).updateOne({ $set: { ...convertedEntityProperties, updatedAt: new Date() } });
    });

    await bulkUpdate.execute(null, { session: transactionSession });
    clearEntityLoadersCache(Collection.modelName, gqlInfo);

    return {
        status: ms.UPDATED,
        data: entitiesToUpdate,
    };
}


Solution

  • It looks like updateOne() is async and expects a callback - documentation

    Where you are doing:

    bulkUpdate.find({ _id }).updateOne({ $set: { ...convertedEntityProperties, updatedAt: new Date() } });
    

    You'll need to provide a callback or possibly just await it.