Ad

Synchronized Update Of Documents Using Mongoose

- 1 answer

I have a nodejs API server deployed in a Kubernetes cluster. Users can send in bids on auction items. To prevent a bid from overriding another there needs to be some synchronization.

I am seeing the following for an incoming bid:

  • start a transaction that reads the current bid and compares it to the incoming bid and updates the record
  • create an aggregation that does the same as above

I don't know which way to go. I also understand that you need to lock the document with either IX or X.

For a RDBMS you would create a transaction that locks the record and releases it after update but I don't know how it works for MongoDB.

Product.findById(productId)
  .then(productmatch => {
    if (productmatch.currentPrice > price) throw Error('no go')

    const bid = new Bid({
      price,
      date: Date.now(),
      user: user._id
    })
    return Product.findByIdAndUpdate(productId, {
        $push: {
          bids: bid
        },
        currentPrice: price,
        currentUser: user,
        currentBid: bid
      }, {
        new: true
      })
      .then(product => {
        if (!product) throw Error(`no go`)

        return bid._id.toString()
      })
  })

Ad

Answer

After a little more research I came up with this solution, however I do not know if its 100% reliable but I believe this method will lock the document and not let any other threads read the document between the query and update operations.

var query = {
    _id: productId,
    closed: false,
    currentPrice: {
      $lt: price
    }
  },
  update = {
    $push: {
      bids: bid
    },
    currentPrice: price,
    currentUser: user,
    currentBid: bid
  },
  options = {
    new: true
  };
return Product.findOneAndUpdate(query, update, options)
  .then(product => {
    if (!product) throw Error(`no product found with id ${productId}`)
    return bid._id.toString()
  })

Ad
source: stackoverflow.com
Ad