0

I'm developing an multiplayer turn based game (e.g chess), should support a lot of players (that's the idea). My question is about a service i'm developing, it's the pairing system, the responsible of pairing 2 players to start a room and start playing.

So, this is the pairing service:

matchPlayers() {
        if (this.players.length >= 2) {
            let player1 = this.players.shift();
            let player2 = this.players.shift();

            if (player1 !== undefined && player2 !== undefined) {
                player1.getSocket().emit('opponent_found');
                player2.getSocket().emit('opponent_found');
                return this.createMatchInDataBaseApiRequest(player1, player2)
                    .then(function (data) {
                        let room = new RoomClass(data.room_id, player1, player2);

                        player1.setRoom(room);
                        player2.setRoom(room);

                        return room;
                });
            }
        }

        return false;
    }

At the entrypoint of the server, each new socket connection I push it to an array "PlayersPool" this array is for players waiting to get matched up.

Right now my approach is to pair users when there are available, (FIFO - first in first out).

The problems (and question) I see with this pairing system is:

  • This depends on new users, this gets executed each time a new user is connected, The flow is: A user connects, get's added to the pool, and check if there are users waiting for being paired, if yes a room is created and they can play, if not he gets added to the waiting pool; Until a new user connects and the code get's executed and so on...

  • What would happen if in some weird case (not sure if this could happen) 2 players gets added to the waiting pool at the same exact time, this service would find the pool empty and would not create a room: To solve this maybe having another service running always and checking the pool? what would be the best approach? Could this even happen? in which scenario?

Thanks for the help.

1
  • 1
    Well, you haven't provided the code that handles incoming connections, adding them to the player pool, or where you're calling matchPlayers() from, etc. But generally, no, it shouldn't be possible for multiple people to be added to the pool at once. Even if two players connect at the exact same moment, the code is not multithreaded, so one player will always be processed before the other. (Though which comes first is likely arbitrary.) Commented Dec 20, 2018 at 14:52

2 Answers 2

2

I'm guessing this particular code snippet is on the server? If so, assuming there is only one server, then there is no "race condition": node.js is single-threaded, as IceMetalPunk mentioned, so if you're running this function every time you add a player to this.players, you should be fine.

There are other reasons to be examining the player pool periodically, though: players you've added to the pool may have gotten disconnected (due to timeout or closing the browser), so you should remove them; you also might want to handle situations where players have been waiting a long time - after X seconds, should you be updating the player on progress, calculating an estimated wait time for them, perhaps spawning an AI player for them to interact with while they wait, etc.

Sign up to request clarification or add additional context in comments.

Comments

1

You can run into a "race condition", it's explained here in this package which provides you a Locking mechanism. https://www.npmjs.com/package/async-lock

That package will be useful, only if you run node.js in a single process, meaning you are not having multiple servers, or having node cluster running multiple processes.

In that case, you will have to implement a distributed locking mechanism which is one of the most complex things in distributed computing, but today you can use the npm package for Redlock algorithm, set 3 redis servers and go. Too much overhead for a game without players.

Node.js is not single threaded, here is the explanation of one of the creators.

Morning Keynote- Everything You Need to Know About Node.js Event Loop - Bert Belder, IBM
https://www.youtube.com/watch?v=PNa9OMajw9w

Conclusion, keep it simple, run it in a single node process and use the "async-lock" package.

If your server grows to become a MMO, you will need to read about distributed computing: How to do distributed locking: https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html

Book on data intensive apps http://dataintensive.net/

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.