Motivation
Once in the
icy winter season during the next planning meeting at work, where everyone used his voting tool - paper maps,
various phone
apps , etc - I was wondering if everyone could sit in the same room when planning could be done from their workers. places, or even from home.
So the idea is to make a remote scheduling service using the Planning Poker technology so popular in the agile world. It is also a little better to understand how socket.io and related technologies work.
Formulation of the problem
Develop a page by which the user enters his name and “room”, then one of the users sets the task in question, everyone votes - when the last of the group has voted - the cards open.
')
The first attempt to implement the protocol
So, having read
this article - the first thought: the browser is a thin client, all logic and state are stored on the server as soon as a new client is connected to a certain room - the server sends out a new snapshot of the state of the room to everyone. The same happens when customers vote, change the topic of discussion, etc.
However, this approach requires some storage on the server (I wanted to avoid using the database, because I wanted to host the project as free as possible). As an option to keep the state in memory - an array or some kind of complex object, but this is fraught with memory leaks.
Second and final implementation
The second approach to solving the problem was to make each individual client responsible for storing his own state and exchange of states with all participants. If we abstract away from socket.io, the protocol can be explained as follows - polite people in a dark room:
- when someone enters
join
- he announces this and calls his name - in response, all the other people in the room call their names and states. - when someone calls their (updated) state
update
- everyone in the room will remember it. - when someone leaves the room
leave
- the server informs all other participants about it and they safely forget about it.
The last point does not fit into the rules of politeness - since the client cannot notify everyone about his disconnection, this function had to be placed on the server - it is the server that is responsible for telling others about the departure of one of the participants:
socket.on('disconnect', function () { var rooms = that.__io.sockets.manager.roomClients[socket.id]; for(var room in rooms) { if ((room != '') && (rooms[room])) { room = room.substring(1); that.__io.sockets.in(room).emit('leave', { room : room, id : socket.id }); } } });
Separately, it is necessary to mention the support of rooms in socket.io, which is not mentioned on the official. site. I got a lot of information from
here . By and large rooms have a logical way to separate all clients connected to the server.
You can enter the room or leave it only from the server side, at the same time you can be in several rooms:
socket.join('room'); socket.leave('room');
The rest of the north - just proxies messages between clients in the same room. The only “business logic” on the server is a restriction on entry into rooms to 12 people. For example, sending an update message in the north looks like this:
socket.on('update', function (data) { data = that.identify(data, socket); that.__io.sockets.in(data.room).emit('update', data); });
Customer
All the logic we have on the client. He is responsible for voting the client (choosing a card), decides when to show the cards of other participants, drops votes when a topic changes and / or new people come. The client also publishes events - this is done in order to separate the client's business logic from the actual manipulations with the DOM, etc. It looks like this:
client.on('reveal', function(){ $('.flippable').each(function(i, val) { setTimeout(function(){ $(val).addClass('flipped'); }, i*50); }); });
Conclusion and Demonstration
In conclusion, I want to say that this approach, though it proved to be not bad, is not without flaws - i.e. There is an opportunity to get into the logic of the client and thus break the synchronization between participants. Also, the votes arrive as soon as someone has voted, they are just not visible until everyone has voted, however, with clever manipulations in Firebug, you can peek at the voices of others.
As a development, you can implement the calculation of the maximum, minimum and average values ​​of maps, as well as implement a simple chat between people in the room - to discuss topics.
as it turned out at the very last moment, Heroku does not support websockets, and had to roll down to long polling - therefore, the
demo offered to you is deprived of one important opportunity - the client does not know in time that one of the participants disconnected, this event does not occur. For a complete familiarization, I suggest you clone
this repository on Github and run it on a local machine, the server script does a check on Heroku and, not finding it, works in a regular way with websockets. Also, for full testing, you will need 2 or more participants.
Good luck!