I'm working on a user-pairing algorithm using socket.io, and it is running on Node.js. I want to make sure that no repeated pairings will happen when people connect in.
The steps of the algorithm as follows:
I'm not sure about whether there would be any race-condition problems during the process of fetching the socketlist of the room. In short, is it possible that a socket in the socketlist would be paired twice, and both pairings succeed?
Here is the code:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms))
io.on('connection', (socket) => {
console.log('New websocket connection', socket.id)
socket.on('match', async (userId, role, classroomId) => {
let roles = { 'retailer': 'supplier', 'supplier': 'retailer' }
room = role + classroomId
otherroom = roles[role] + classroomId
socket.userId = userId
socket.join(room)
for (let i = 0; i < 60; ++i) {
if (socket.rooms.has(room)) {
const sockets = await io.in(otherroom).fetchSockets()
if (sockets.length > 0
&& io.sockets.sockets.get(socket[0].id).rooms.has(otherroom)) {
const teammate = io.sockets.sockets.get(sockets[0].id)
console.log(teammate.userId)
console.log(room, otherroom)
socket.leave(room)
teammate.leave(room)
const pair = await models.Pair.create({
supplierId: role == 'supplier' ? userId : teammate.userId,
retailerId: role == 'supplier' ? teammate.userId : userId,
currentTime: new Date().toISOString().slice(0, 10)
})
io.to(teammate.id).to(socket.id).emit('match-success', pair)
console.log((role == 'supplier' ? 's' : 'r'), pair)
break
}
console.log(socket.id, i)
// if no match, rematch every 5 seconds.
await wait(5000)
} else {
break
}
}
socket.on('join', (room) => {
console.log('join' + room)
socket.join(room)
})
socket.on('leave', (room, callback) => {
socket.leave(room)
callback()
})
})
})