I'm developing a match-making system for a game where each match involves two players.
waiting-users-queue collection:
user_id (String)
status (String)
Here's the logic I'm trying to implement:
- When a user joins the system, I check the waiting-users-queue for any users with the status WAITING.
- If there's a user waiting, I update their status to MATCHED and proceed with starting the game for both users.
- If no user is waiting, I will insert the new user into the queue with the status WAITING.
I've explored MongoDB's documentation and attempted to use transactions, but they require a replica set, which I don't have in my setup.
I've also tried implementing manual locking using a separate collection for locking status.
async function acquireLock(lockId){
return new Promise((resolve,reject)=>{
let intervalId;
intervalId = setInterval(async () => {
const lockData = await Lock.findOneAndUpdate({ lock_id: lockId, status: 'FREE' }, { status: "LOCKED" });
if (lockData) {
console.log('Lock acquired for ', lockId);
resolve(clearInterval(intervalId));
}
});
})
}
async function releaseLock(lockId){
return Lock.findOneAndUpdate({ lock_id: lockId }, { status: "FREE" })
}
Flow :
-> New user join request
-> Call acquireLock() and wait until the lock to acquire
-> Check if any user is in the waiting queue
-> If yes: update that user's status to MATCHED and start the game for both users
-> If no: insert new user into the waiting queue
-> Call releaseLock() to release the lock
This way, I can ensure that only one request is processed at a time, even if multiple requests come from different clients simultaneously, effectively handling concurrency.
However, I prefer to utilize MongoDB's built-in support for locking to avoid managing locks manually.
Could someone guide me on how to correctly set up read and write locking for MongoDB collection in this context?