Hey @Naisarg_Parmar,
OK I spent a couple of hours on this and I think I understand the problem.
From what I see, you are trying to limit the number of documents in this collection to 5 and you tried to secure this in a transaction to ensure this - but the logic is flawed.
Let me explain what I have on my side and how I came to this conclusion. I wasn’t able to get Jmeter to work, but I created this little bash script to send 10 POST queries in parallel.
#!/usr/bin/env bash
seq 1 10 | xargs -n1 -P10 curl -X POST 'http://localhost:3001/insert' -H 'Content-Type: application/json' -d '{"doc": "Max"}'
When I execute this script, here is what I get in the server logs:
Server is running on PORT 3001
Database connected
body: { doc: 'Max' }
body: { doc: 'Max' }
body: { doc: 'Max' }
body: { doc: 'Max' }
body: { doc: 'Max' }
body: { doc: 'Max' }
body: { doc: 'Max' }
body: { doc: 'Max' }
body: { doc: 'Max' }
body: { doc: 'Max' }
1 booking_count: 0
1 booking_count: 0
1 booking_count: 0
1 booking_count: 0
1 booking_count: 0
1 booking_count: 0
1 booking_count: 0
1 booking_count: 0
1 booking_count: 0
1 booking_count: 0
2 insertedRecord: new ObjectId("616b6048d6ae6b6f3d7acfa9")
2 insertedRecord: new ObjectId("616b6048d6ae6b6f3d7acfaa")
2 insertedRecord: new ObjectId("616b6048d6ae6b6f3d7acfab")
2 insertedRecord: new ObjectId("616b6048d6ae6b6f3d7acfac")
2 insertedRecord: new ObjectId("616b6048d6ae6b6f3d7acfad")
2 insertedRecord: new ObjectId("616b6048d6ae6b6f3d7acfae")
2 insertedRecord: new ObjectId("616b6048d6ae6b6f3d7acfaf")
2 insertedRecord: new ObjectId("616b6048d6ae6b6f3d7acfb0")
2 insertedRecord: new ObjectId("616b6048d6ae6b6f3d7acfb1")
2 insertedRecord: new ObjectId("616b6048d6ae6b6f3d7acfb2")
Transaction Success
Transaction Success
Transaction Success
Transaction Success
Transaction Success
Transaction Success
Transaction Success
Transaction Success
Transaction Success
Transaction Success
As you can see, the 10 requests where all received exactly at the same time and they all entered in their own transactions at the same time.
Within EACH transaction, you read the number of document in this collection. They all read zero
as nothing was inserted yet. From this point on, it means that your 10 transactions are valid and you can insert your document as you can pass in the true
branch of the IF statement.
Result: ALL the transactions succeed and you end up with 10 documents in your database.
Now that this is done and these transactions are committed, if I try the same thing again, the 10 transactions are aborted as the document count is now equal to 10.
The code in its current state “works”. But it’s not a valid implementation to limit the number of documents in a collection.
The reason is that you cannot read what is happening in another transaction running in parallel. That’s the principe of read isolation and there is no way to go around that as far as I know.
Basically, each transaction is self standing and should be self sufficient. Here, you are trying to access data outside the transaction and that just cannot work.
So in the end, I don’t know how to solve your problem as I’m not sure what problem you are trying to solve.
If you are trying to limit the number of documents in a collection to 5 though, I would use a capped collection:
test [direct: primary] test> db.bookings.drop()
true
test [direct: primary] test> db.createCollection("bookings", {capped:true, size:999999999, max:5})
{ ok: 1 }
test [direct: primary] test> for (let i=0; i<7; i++){ db.bookings.insertOne({nb: i})};
test [direct: primary] test> db.bookings.find()
[
{ _id: ObjectId("616b6717fa19ded77023e3bc"), nb: 2 },
{ _id: ObjectId("616b6717fa19ded77023e3bd"), nb: 3 },
{ _id: ObjectId("616b6717fa19ded77023e3be"), nb: 4 },
{ _id: ObjectId("616b6717fa19ded77023e3bf"), nb: 5 },
{ _id: ObjectId("616b6717fa19ded77023e3c0"), nb: 6 }
]
But note that you cannot write in capped collections in transactions since MongoDB 4.2.
Cheers,
Maxime.