Implementing Real-Time Results

Since we were looking into making things go real time, I took the opportunity to read up more on network related topics and this post shall cover what it was that I read through and learnt.

TCP/IP vs UDP

Taking the opportunity to look into the existing internet protocols, I had to touch on TCP/IP with all the OSI mumbo jumbo. I skimmed through this resource from Yale on TCP IP, and found out cool things like how it’s basically first invented for military purposes.

Then also after getting a better understanding of that, I also wanted to find out more on why not UDP? (Transport layer)

Websockets

Jon explained that there is this new thing in HTML5 known as websockets and how it has made internet awesome. There were several other ‘primitive’ and arcade ways we could have made our polling system “live” with techniques such as long-polling, which basically sets the page to refresh every few seconds (this sends requests to the server for the page to load the new results). Doing so may actually DDoS the server.

And since we were doing things the Angular way, we had to read up on Angular websockets.

Socket.io

Thankfully there are also libraries out there for us to implement. Discovered Socket.io earlier on when we were discussing on how to implement the real-time/live results in our results page. Finally arriving at the point where we actually have to do it, we found ourselves back here.

We were kind of lucky that Socket.io recently patched and upgraded their stuff to v1.0. This meant that there was more support for Express framework and more documentation was provided.

Just with the following lines of code, we were able to set up Sockets to work immediately with our Express server.

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(80);

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/index.html');
});

io.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

However, getting Socket.io to work with our model layer was not easy, and we had run into several problems. Jon took over on this part to configure and fix up the entire websocket implementation for socket.io in this commit.

I guess the important take away here is that we have to think in terms of a ‘chat room’, that each time a socket is open, it serves the data posted by a user on another client to all the other users who are listening in the room. Which is essentially represented in this following snipper of code:

module.exports = function(app, io) {
 
   io.sockets.on('connection', function (socket) {
 
     socket.on('subscribe', function(room) {
       var roomPath = room.split('/');
       switch(roomPath[0]) {
         case 'results':
           // TODO verify socket.request.user is authorized to view results for poll
           socket.join(room);
           break;
       }
     });
     socket.on('unsubscribe', function(room) {
       socket.leave(room);
     });
 
   });
 
 };

Pusher and real-time push

Also read about Pusher, which is a hosted API for quickly, easily and securely adding scalable realtime functionality to web and mobile apps.

Phew. That was heavy.