0

I'm making a simple game engine, which implements room manipulation.

I was thinking a lot and still have doubts that I'm making rooms not in the valid way.

Here's the scenario.

1) There's one static room, where users are able to 'register'. 2) after certain number of users are registered, it should create dynamic room and put these certain number of users in that room and make them quit the static room.

So, if we run this in multiple instances and let's say we're waiting for 2 users.

2 users join the static room -> create new room (in redis) -> enter these two players in that room (subscribe) -> make those players to leave static room (queue-like system).

Now what I think is a problem.

2 users join the static room -> before creating new room, one other player joins static room (different node instance) -> create new room -> move two players there -> other instance still thinks there's enough users to create new room -> something weird happens.

Is this correct? How should I implement the queue style room?

Nika
  • 1,864
  • 3
  • 23
  • 44

2 Answers2

1

You need atomic operations: put all of these 4 steps into a transaction. With Redis, you can use either Transaction or Lua Scripting to achieve it.

With lua scripting, you can have a script like this:

-- add new user to static room
redis.call('lpush', 'static_room', ARGV[1])

-- if the number of static room reaches the limit
local num = redis.call('llen', 'static_room')
if num == 2  then
    -- get the room number for a new dynamic room
    local new_dynamic_room_num = redis.call('incr', 'dynamic_room');
    local dynamic_room = 'dynamic_room' .. new_dynamic_room_num

    -- move all users from static room to dynamic room
    while true do
        local num = redis.call('llen', 'static_room')

        if num == 0 then break end

        redis.call('rpoplpush', 'static_room', dynamic_room)
    end
end

Since the lua script executes atomically, no other user can join the static room before we finish moving all users from the static room to dynamic room.

for_stack
  • 21,012
  • 4
  • 35
  • 48
  • You're absolutely right, but I'd like to know one, is there any native javascript way to do those atomically? – Nika Oct 16 '16 at 14:35
0

A solution could be to make all non connected players enter in one unique node instance, which is in charge of creating rooms and assigning players to these rooms. Then, once they are assigned to a given room, it redirects them to the node instance in charge of this room.

Pascal Le Merrer
  • 5,883
  • 20
  • 35
  • That makes no sense using node cluster then. – Nika Oct 16 '16 at 14:35
  • It makes sense because the first instance is just an entrypoint. Once a user is affected to a room it will be handled by another instance in the cluster. – Pascal Le Merrer Oct 16 '16 at 14:41
  • So it should be master I guess? Or how can I do such thing, I don't even know on which node instance client connects to – Nika Oct 16 '16 at 15:00
  • Yes, the first connection could be done to the master, with a classic http request ; then you open a websocket between a child and the client. – Pascal Le Merrer Oct 16 '16 at 15:36