Search code examples
mongodbmongoosetransactions

Why is mongo saving changes even though the transaction fails?


Code:

const session = await mongoose.startSession();
session.startTransaction();
try {
  const model = mongoose.model("cars");
  const document = { _id: "6059edf7fc81428fcc0b5c33" };
  await model.create(document);
  await model.create(document); // illegal duplicate key

  await session.commitTransaction();
  session.endSession();
} catch (error) {
  await session.abortTransaction();
  session.endSession();
}

Expected behavior: I expect the whole operation to fail, with no entries inserted into the databse

Actual behavior: the commitTransaction() is not called, since the second create() fails; the abortTransaction() is called, but after the code is executed, the database has the first entry.

Seems like this question describes the same thing, but no answers: Why does some documents get saved in mongoose transactions eventhough the transaction fails


Solution

  • I think you need to explicitly pass the session to every operation you want to be part of the session.

    Here is an example from the documentation :

    session.startTransaction();
    
    // This `create()` is part of the transaction because of the `session`
    // option.
    await Customer.create([{ name: 'Test' }], { session: session });
    

    Applying the same to your code:

    const session = await mongoose.startSession();
    session.startTransaction();
    try {
      const model = mongoose.model("cars");
      const document = { _id: "6059edf7fc81428fcc0b5c33" };
      await model.create(document, {session: session});
      await model.create(document, {session: session}); // illegal duplicate key
    
      await session.commitTransaction();
      session.endSession();
    } catch (error) {
      await session.abortTransaction();
      session.endSession();
    }