by James Coglan

Menu

I’m doing my traditional birthday software announcement a little early
this year, mostly because I really want to get this out and partly because I’m
doing a lot of little bits of work on old projects at the moment and this is the
only fancy new thing I’ve got to show.

Spurred on by the sheer volume of awesome emanating from Music Hack Day
over the weekend – a few Songkickers went over, I caught the demos via the live
stream – I decided to revisit a project I worked on just before the London MHD
about six months ago. My hack was this little web service that exposed your
iTunes library over HTTP and let you broadcast what you were listening to to
other browsers via Comet. The Comet part of it was handled by an early version
of Faye, a Ruby server and JavaScript client I cooked up to provide
client-to-client messaging.

The Ruby version still exists, and just gained support for Thin’s async response
feature, making it totally non-blocking when used behind Thin. The more exciting
news is that I’ve also ported the backend to Node.js, a JavaScript
environment optimised for non-blocking asynchronous I/O. This makes it much
better at serving highly concurrent Comet requests since it uses an event loop
rather than blocking threads to respond to each request. It’s a straight port of
the Ruby version, which is entirely event-driven except for the web server
interface, since Rack expects a synchronous return to respond to requests.

Anyway, onto the code. The backends are trivial to set up, and both currently
reside in a single process and keep all channel data in memory. This means you
can’t use it behind Passenger (which spawns multiple Ruby processes to serve an
app) but I’m hoping some bright spark can help with scaling it. Consider it a
fun and reasonably nippy toy right now, I guess. To set up a backend:

More complete usage examples are available in the Git repo. Both these
backends provide an endpoint at http://0.0.0.0/comet that speaks the Bayeux
protocol, and clients can use this to route messages between each other.

Each client (i.e. a JavaScript program running in a browser) can subscribe to
named channels and publish arbitrary JavaScript objects to channels. Each
message is distributed by the server to all the clients subscribed to that
channel, and clients use a callback to handle messages from the channel.

// I can publish a message ...CometClient.publish('/my/channel',{msg:'Hello world!'});// .. and you can pick it upCometClient.subscribe('/my/channel',function(message){alert(message.msg);});

Using this it’s absolutely trivial to make simple client-to-client messaging
apps – the repo contains the obligatory chat demo, which I’ve modelled on
Twitter to illustrate different uses of subscriptions. You don’t need any
server-side code for this aside from starting the Faye backend up to handle
message routing. The next step would be to provide a client interface on the
server side so your backend code can send data out to clients, but we’ll save
that for a future release. Contributions in the form of scaling advice and
server-side client suggestions would be very much appreciated, in the meantime
go have a play with the code.

—

If you’ve enjoyed this article, you might enjoy my recently published book
JavaScript Testing Recipes. It’s
full of simple techniques for writing modular, maintainable JavaScript apps
in the browser and on the server.