Sunday, August 11, 2013

Erlang WebSockets Meet D3.js


1. Live Demo on Google Compute Engine: click here
2. Download complete source code: click here 

Chapter III of our tutorial - Intro

On the last  chapter, we used ChicagoBoss web framework to build our Erlang-based MVC web site, using Angular JS and Twitter Bootstrap to build a template-based, database-driven website. Our hosting environment is Google Compute Engine, which allows for great flexibility and scalability. 

On this chapter, we will see how we can use ChicagoBoss WebSocket controllers to implement an HTML5 WebSockets Application.

We will be creating a socket service that is able to receive and send data in order to create a game-like real-time mechanism. We will also be using D3.js JavaScript library to establish our game graphics. 

We will build upon the website that we created on our previous chapter by adding a view called "nodes", so please read through that before diving in this one. 

Goals

1. We want to write a simple WebSocket service that will be able to both send and receive messages in real-time.
2. We want a nice little client-side JavaScript app that will use HTML5 WebSockets in order to send and receive data from our server. 

Creating The Erlang WebSocket Service 

To create the WebSocket service, will will build upon our Erlang-based web application from the last chapter. We will do by simply adding a single new controller - a WebSockets controller. This is done easily in ChicagoBoss web framework as we will be seeing soon. 

Every ChicagoBoss WebSocket must implement a set of functions: straightforward functionality to handle a user joining the connection, leaving it, handle an incoming message, broadcast a message to all connected sockets, etc.

Join

Whenever a request to connect to the socket is received, an Erlang Pid (process ID) and a SessionID are passed to us. We handle the join request by storing these in an erlang dictionary, using the WebSocketPid as the key and the SessionID as the value.

Incoming Message (from client to Server)

Whenever a client sends our socket service a request, we want to send out this message to all our connected users. This can be done pretty amazingly with Erlang list comprehensions: we first define an anonymous function that would send an Erlang message to X, where X is an Erlang process corresponding to a WebSocketPid. Then we define a variable to represent all of our currently connected users (the list of keys from our dictionary that stores all of the WebSocekt Pids). Then, we execute our function over all Erlang processes in our store - except for the currently running Pid.

The Client Side (HTML5 WebSockets and SVG)
The View

To communicate with our erlang websocket, we will be adding a new view to our angular.js app: 

$routeProvider.when('/nodes', {templateUrl: 'partials/nodes.html', controller: 'NodesCtrl'});

This view is nothing fancy: just some text and an element that we will be using to append our SVG graphics to.

notice the <p> tag with id="websockets", we're going to append our SVG to this little fellow later.

The Controller

To illustrate the passing of messages, I've taken up the D3.js build your own graph demo and changed it a bit to allow users to add nodes and build a shared graph in real time using web sockets. 

The interesting methods are:
onmousedown

here, whenever a node is added to the graph (when the user releases the mouse click), we use our webSocketsDataFactory to send this data to our socket service.


this factory just serves as a proxy for calling the WebSockets object, which we define as a global var for the simplicity of the design in this tutorial (we will want to access the WebSocket elsewhere). 

var socketService = new WebSocket("ws://localhost:8001/websocket/nodes_service", "nodes_service");



Next up is our onmessage method, which will be fired when our Erlang socket service copies data from an incoming client to all clients (including this one).

When a message is received from the server, we will use that data to add a new node to our graph.

And That's That!

On our next chapter, we will learn how to use BossDB to persists data to riak nodes on Google Compute engine, so that we will be able to log user messages generated on our real time system. 

No comments:

Post a Comment