'Document Read and insert with locking/transaction in nodejs with mongodb

In reservation system, only 5 different user can create bookings. If 100 user call booking api at same time than how to handle concurrency with locking. I am using nodejs with mongodb. I went through mongo concurrency article and transactions in mongodb, but cannot find any sample coding solution with locking.

I have achieved solution with Optimistic concurrency control (when there is low contention for the resource - This can be easily implemented using versionNumber or timeStamp field).

Thank you in advance for suggesting me solution with locking.

Now the algorithm is:

Step 1: Get userAllowedNumber from userSettings collection.

//Query
db.getCollection('userSettings').find({})

//Response Data
{ "userAllowedNumber": 5 }

Step 2, Get current bookedCount from bookings collection.

//Query
db.getCollection('bookings').count({ })

//Response Data
2

Step 3, if bookedCount <= userAllowedNumber then insert in bookings.

//Query
db.getCollection('bookings').create({ user_id: "usr_1" })


Solution 1:[1]

I had indepth discussion about locking with transaction in mongodb community. In the conclusion, I learn and found the limitation of transaction. There is no lock we can use to handle concurrent request for this task.

You can see the full Mongodb community conversation at this link https://www.mongodb.com/community/forums/t/implementing-locking-in-transaction-for-read-and-write/127845

Github demo code with Jmeter testing shows the limitation and not able to handle concurrent request for this task. https://github.com/naisargparmar/concurrencyMongo

New suggestion are still welcome and appreciate

Solution 2:[2]

For a simple example of transaction, first you need to have a client connect to a MongoDB.

const client = new MongoClient(uri);
await client.connect();

Once you have the client, you can create a session from which you can make transactions:

const session = await client.startSession();
const transactionResults = await session.withTransaction( async () => {
     await client.db().collection("example").insertOne(example);
}, transactionOptions);

With transactionOptions being:

const transactionOptions = {
   readPreference: 'primary',
   readConcern: { level: 'majority' },
   writeConcern: { w: 'majority' }
};

Find about the Read/Write concern in the MongoDb documentation. Depending on your usecase, you may also consider findAndModify which lock the document on change.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2