What approach should I take for creating a "lobby" in Node.js?

Problem

I have users connecting to a Node.js server, and when they join, I add them into a Lobby (essentially a queue). Any time there are 2 users in the lobby, I want them to pair off and be removed from the lobby. So essentially, it's just a simple queue.

I started off by trying to implement this with a Lobby.run method, which has an infinite loop (started within a process.nextTick call), and any time there are more than two entries in the queue, I remove them form the queue. However, I found that this was eating all my memory and that infinite loops like this are generally ill-advised.

I'm now assuming that emitting events via EventEmitter is the way to go. However, my concern is with synchronization. Let's assuming my Lobby is pretty simple:

Lobby = {
  users: []

, join: function (user) {
    this.users.push(user);
    emitter.emit('lobby.join', user);
  }

, leave: function (user) {
    var index = this.users.indexOf(user);
    this.users.splice(index, 1);
    emitter.emit('lobby.leave', user);
  }
};

Now essentially I assume I want to watch for users joining the lobby and pair them up, maybe something like this:

Lobby = {
  ...

, run: function () {
    emitter.on('lobby.join', function (user) {
      // TODO: determine if this.users contains other users,
      //       pair them off, and remove them from the array
    });
  }
}

As I mentioned, this does not account for synchronization. Multiple users can join the lobby at the same time, and so the event listener might pair up a single user with multiple other users instead of just one.

Can someone with more Node.js experience tell me if I am right to be concerned with this event-based approach? Any insight for improvement on this approach would be much appreciated.

Problem courtesy of: Matt Huggins

Solution

You are wrong to be concerned with this. This is because Node.JS is single-threaded, there is no concurrency at all! Whenever a block of code is fired no other code (including event handlers) can be fired until the block finishes what it does. In particular if you define this empty loop in your app:

while(true) { }

then your server is crashed, no other code will ever fire, no other request will be ever handled. So be careful with blocks of code, make sure that each block will eventually end.

Back to the question... So in your case it is impossible for multiple users to be paired with the same user. And let me say one more time: this is simply because there is no concurrency in Node.JS!

On the other hand this only applies to one instance of Node.JS. If you want to scale it to many machines, then obviously you will have to implement some locking mechanism (which ensures that no other process can work with the data at the same time).

Solution courtesy of: freakish

Discussion

There is currently no discussion for this recipe.

This recipe can be found in it's original form on Stack Over Flow.