WebSockets: The joys of Instant Gratification
or How I stopped the Curse of the never ending Nag.
If you have built a web site tossing up real time data, most likely it is powered by AJAX requests. You are stuck in the never ending dance of polling. Is there stuff? How about now? Should I come back in 100ms? 200ms? Over the years I have built several of these and there is always a code explosion trying to juggle getting the data as fast as possible without melting the servers with a mound of nagging “Is it done yet”. If only there could be a two way conversation on the same connection.
Trumpet sound Well hello WebSockets. A new protocol for a full duplex TCP connection, meaning a two way conversation in a connection (more trumpet sounds). Now instead of constantly checking for new data, you simply have to open the WebSocket and the data will be pushed as it arrives. Ahh, instant gratification. No nagging for data, it just flies in.
Torquebox makes getting a WebSocket services up and running really easy. This is achieved by using Stomplets and passing data using Stomp. The Stomp messages are passed from the Browser client to Torquebox, which are placed on a queue. The queue doles out the messages to the Stomplet, which handles how the message is processed.
A crude diagram of what is going on:

The good news is all of this boils down to a few libraries and some tweaks to Torquebox.
Configuring for WebSockets
For WebSockets to work a few configurations need to be set. First, you will need the latest version of Torquebox, 2.3.1. Next Torquebox needs to control the web session. This enables the session to be passed along with Stomp message, which is important for allow a Stomplet to authenticating a message. For Rails, add an initializer that sets the session_store to :torquebox_store:
# config/initializer/torquebox_init.rb AppName::Application.config.session_store :torquebox_store
Next, the Stomplet needs to be configured. This maps the Stomplet to the queue the Stomp messages are sent to. This is set in the Torquebox config, for example using the DSL:
# config/torquebox.rb TorqueBox.configure do stomplet DemoStomplet do route '/queues/demo' end end
Note: the default port used is 8675
With configuration complete, you can add your Stomplet. A client will subscribe, send message(s), receive message(s), and unsubscribe to a queue that is managed by the Stomplet. Fairly straight forward, the Stomplet keeps track of subscribers to the queue, sends messages to the subscribers, and removes them when they unsubscribe. A Stomplet has full access to your Rails stack, Torquebox spins up a separate pool of Rails instances that are used for the Stomplet. This is a simple working demo based on the one from the docs that relays the message sent to all subscribers:
require 'torquebox-stomp' class DemoStomplet def initialize() super @subscribers = [] end def configure(stomplet_config) end def on_message(stomp_message, session) # send the message to each subscriber @subscribers.each do |subscriber| subscriber.send( stomp_message ) end end def on_subscribe(subscriber) # add a new subscriber @subscribers << subscriber end def on_unsubscribe(subscriber) # remove subscriber @subscribers.delete( subscriber ) end end
A more complicated demo Stomplet that shows how to use the session for authentication. Has support for a pass through token to allow local requests, otherwise it checks the User model for an authentication token.
With the server set up, now it is time to set up a client. The library stilts-stomp-client.js (Torquebox ships with the lib) handles the work of communicating over Stomp to Torquebox:
// Stomp client for url client = Stomp.client("ws://localhost:8675/"); // Connect to Torquebox, executing the function when connected client.connect("", "", function(frame) { // Subscribe to the demo queue to fire callback client.subscribe("/queue/demo", function(msg) { alert(msg); }); // Send a test message client.send( "/queue/demo", {}, "This is a test of the Demo" ); }); // Disconnect client on close $(window).unload(function() { client.disconnect(); });
This will connect to ws://localhost:8675/, subscribe to the /queue/demo queue to fire the callback every time a message is received to open a popup, and then send a test message.
Similar to the JavaScript client, the stilts-stomp-client gem handles sending the work of sending Stomp messages:
client = StompClient.new( "stomp://localhost:8675/" ) client.connect client.send( "/queues/demo", "test" ) client.disconnect # this gives an error from the present gem
The StompClient is an implementation of the Java version and it still a bit rough around the edges. I added support for sending headers and fixed the disconnect error in the Ruby client - (https://gist.github.com/mguymon/5650321).
Now, go have some fun, fire off some message in your rails console and see them instantly appear in the browser. Neat! Normally this sort of step up is a colossal pain the in ass to get chugging along, but I got it all up in running in a few hours.
With making WebSocket this accessible, I look forward to seeing it used more instead of AJAX. Now instead of a dozen AJAX request going out, followed by untold number more sniffing around for new data, a single WebSocket connection could slurp down all the data, updates and all.