Let’s imagine we have the following collections
Users
- id
- nickname
- inChat
- createdAt
Chats
- id
- user1
- user2
Now on the server we have a method, which is called by a user who want to chat with somebody:
connectChat: function () {
Meteor.users.update(this.userId, {$unset:{'chatId':''}});
var ownAccount = Meteor.users.findOne(this.userId);
var finalUser = _.sample(Meteor.users.find({
_id: {$ne: this.userId},
'chatId': {$exists:false}
}).fetch());
//Okay, did we get a new user?
if (finalUser) {
var chat = Chats.findOne({
$or: [{user1: this.userId, user2: finalUser._id}, {
user1: finalUser._id,
user2: this.userId
}]
});
var chatId = null;
if (chat) {
chatId = chat._id;
} else {
chatId = Chats.insert({user1: this.userId, user2: finalUser._id, createdAt: new Date()});
}
Meteor.users.update(this.userId, {$set: {'chatId': chatId}});
Meteor.users.update(finalUser._id, {$set: {'chatId': chatId}});
}
}
This works fine, but has a big disadvantage: Sometimes, when multiple users call the function at the same time, they are joining chat rooms, where the other user isn’t in, because he also requested a chat and was connected to some other user.
How can I prevent such a behavior? What is the best way to handle such “same time requests”? My only idea for the moment is a cron job, which is running every 4 seconds and scans for users without a chat room - but this would be a problem if I scale my app to multiple instances.