Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Given transaction number 1 does not match any in-progress transactions #15091

Open
1 task done
ThakurSaad opened this issue Dec 13, 2024 · 1 comment · May be fixed by #15100
Open
1 task done

Given transaction number 1 does not match any in-progress transactions #15091

ThakurSaad opened this issue Dec 13, 2024 · 1 comment · May be fixed by #15100
Labels
help wanted help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary

Comments

@ThakurSaad
Copy link

Prerequisites

  • I have written a descriptive issue title

Mongoose version

^8.8.2

Node.js version

20.18.0

MongoDB version

^6.11.0

Operating system

Windows

Operating system version (i.e. 20.04, 11.3, 10)

10.0.26100

Issue

Code

const joinEvent = async (user, payload) => {
  const { userId } = user;
  const { eventId, slotId, data } = payload;

  const session = await mongoose.startSession();
  session.startTransaction();

  validateFields(payload, ["eventId", "price", "data"]);

  const [event, slot] = await Promise.all([
    Event.findById(eventId),
    EventSlot.findById(slotId),
  ]);

  if (!event || !slot)
    throw new ApiError(
      status.NOT_FOUND,
      `${event ? "Slot" : "Event"} not found`
    );

  if (event.status !== ENUM_EVENT_STATUS.OPEN)
    throw new ApiError(
      status.BAD_REQUEST,
      `Event is no longer open (status: ${event.status}).`
    );

  // check seat availability
  const totalPeople = slot.currentPeople + 1;
  if (totalPeople > slot.maxPeople)
    throw new ApiError(status.BAD_REQUEST, `No seats available`);

  // map through the payload and create bookings to save
  const bookingData = [];
  data.map((obj) => {
    validateFields(obj, ["bookingFor", "moreInfo"]);

    if (!obj.moreInfo.length)
      throw new ApiError(status.BAD_REQUEST, "moreInfo can't be empty");

    bookingData.push({
      user: userId,
      host: event.host,
      event: eventId,
      eventSlot: slotId,
      startDateTime: event.startDateTime,
      endDateTime: event.endDateTime,
      price: payload.price,
      numOfPeople: 1,
      bookingFor: obj.bookingFor,
      moreInfo: obj.moreInfo || null,
    });
  });

  try {
    const bookings = await Booking.create(bookingData, { session });

    console.log(bookings);

    await session.commitTransaction();

    return bookings;
  } catch (error) {
    await session.abortTransaction();
    throw new ApiError(status.BAD_REQUEST, error.message);
  } finally {
    session.endSession();
  }
};

Summary of code

  • The transaction validates the input, checks event and slot availability, ensures there are seats, and creates booking records in the database. If any step fails, it rolls back; otherwise, it commits.

  • Booking Data Preparation:
    Iterates over the data array in the payload, validating and mapping its properties (bookingFor and moreInfo) to prepare booking records for the database.

Error

Given transaction number 1 does not match any in-progress transactions. The active transaction number is -1

When I save each document individually, the issue does not occur. Only occurs when I try do save multiple documents in an array of object format.

Here comes the funny thing. The error, it doesn't occur every time, sometimes there is error and sometimes there are no error. And the error differes each time if I keep hitting the code continuously.

Examples of the errors

Given transaction number 4 does not match any in-progress transactions. The active transaction number is 4
Given transaction number 5 does not match any in-progress transactions. The active transaction number is 5
Given transaction number 48 does not match any in-progress transactions. The active transaction number is 47

The number keeps increasing. Some success some errors.

Why is it happening?

@ThakurSaad ThakurSaad added help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary help wanted labels Dec 13, 2024
@vkarpov15
Copy link
Collaborator

MongoDB does not allow multiple operations in the same transaction in parallel, so create() on multiple docs with a session option may fail because create() saves multiple documents in parallel by default.

You can either use insertMany(), or use the ordered option for create() as follows:

// Insert multiple bookings within a transaction
const bookings = await Booking.create(bookingData, { session, ordered: true });

We will add a more helpful error in this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted help This issue can likely be resolved in GitHub issues. No bug fixes, features, or docs necessary
Projects
None yet
2 participants