MongoError: WriteConflicts

Viewed 113

Schema definitions Users collection: (optimisticConcurrency: true)

{
  _id: [Object Id],
  pingedAt: [Date],
  currentBal: [Int32],
  { ...otherUserAttibutes }
}

Bookings collection (no optimisticConcurrency imposed on this collection)

{
  _id: [Object Id],
  user: [Ref to User -> the user for whom the booking was made],
  status: [0, 1, 2, 3, ...]
  { ...otherBookingAttributes }
}

All api calls to the backend have an authenticate() middleware to cross, which authenticates by querying for the user after validating the token in the auth header. Then retrieves the user object and ends up updating the following attribute

pingedAt → current Date

Scenario causing the issue:

  1. At 12:01:01:100 ms /cancel-booking/:bookingId - PUT call was initiated and a mongoose session is started.
    const session = await mongoose.startSession();
    session.startTransaction();
    const booking = await this.bookingsRepository.getBookingWithSession({ _id: bookingId }, session)
  1. At 12:01:01:200 ms user makes /bookings - GET call and at 12:01:01:250 ms the user’s pingedAt is updated during authentication.
    user.pingedAt = new Date();
    await user.save();
  1. By 12:01:01:300 ms, the booking that was retrieved with session is changed to CANCELLED
    booking.status = 3
    await booking.save({ session })
  1. In the same cancel booking call, we add money to user’s wallet. Say booking fee is 300/-. At 12:01:01:350 ms we save user object with updated balance.
    booking.user.currentBal = booking.user.currentBal + 300
    await booking.user.save({ session });

WriteConflict error is thrown as the same user object has already changed at 12:01:01:250 ms

Error logs

MongoError: WriteConflict
  at MessageStream.messageHandler (/home/ubuntu/api.backend.js/node_modules/mongodb/lib/cmap/connection.js:268:20)
  at MessageStream.emit (events.js:315:20)
  at MessageStream.EventEmitter.emit (domain.js:483:12)
  at processIncomingData (/home/ubuntu/api.backend.js/node_modules/mongodb/lib/cmap/message_stream.js:144:12)
  MessageStream._write (/home/ubuntu/api.backend.js/node_modules/mongodb/lib/cmap/message_stream.js:42:5)
  at doWrite (_stream_writable.js:403:12)
  writeOrBuffer (_stream_writable.js:387:5)
  at MessageStream.Writable.write (_stream_writable.js:318:11)
  at TLSSocket.ondata (_stream_readable.js:716:22)
  at TLSSocket.emit (events.js:315:20)
  at TLSSocket.EventEmitter.emit (domain.js:483:12)
  at addChunk (_stream_readable.js:295:12)
  at readableAddChunk (_stream_readable.js:271:9)
  at TLSSocket.Readable.push (_stream_readable.js:212:10)
  at TLSWrap.onStreamRead (internal/stream_base_commons.js:186:23)
  at TLSWrap.callbackTrampoline (internal/async_hooks.js:120:14)}
0 Answers
Related