/badger-js

Badger is designed as a Javascript library to act as a the `subscriber` in a Publish / Subscribe system. It's API is designed to flexible enough to work with any kind of channel (XMPP, polled Atom, ...)

Primary LanguageJavaScriptMIT LicenseMIT

Badger Build status

Badger is designed as a Javascript library to act as a the subscriber in a Publish / Subscribe system. The motivation for this is to allow updates from a server to notify the browser based clients as quickly as possible.

Badger is written in a modular fashion so that different technologies can be used for the channel. For instance:

  • XMPP Pubsub
  • Polled Atom feeds
  • ...

There is also provision for fallbacks. This allows multiple channels to be used. This can be used to help aid development (where a channel may not be available), or add resilience (where browser capabilities, or the network link quality are insufficient).

Callbacks are then used to allow Badger to be integrated into the rest of the system.

Usage

In order to avoid any namespace conflicts Badger uses the public namespace com.jivatechnology (reverse DNS scheme). You can import this into your local scope with something like:

var Badger = com.jivatechnology.Badger;

Badger allows you to easily specify nodes that you are interested in. First off you will need an instance of a Badger.Coordinator (sounds fancy doesn't it):

var badger = new Badger.Coordinator();

From here we can tell our badger to start listening out for things:

badger.subscribe('mash potato');
badger.subscribe('worms');

Or stop listening for things:

badger.unsubscribe('carrots');

We can also add callbacks (see Callback docs) to specify what to do when these events are raised:

  • onSubscribeSuccess passing node
  • onSubscribeFailure passing node
  • onUnsubscribeSuccess passing node
  • onUnsubscribeFailure passing node
  • onMessage passing node,id,verb,payload

For example:

badger.onMessage.add(function(node,id,verb,payload){
  ...
  Message handling code
  ...
});

Or we can add a handler that is specific to a certain node:

badger.subscribe('mash potato').onMessage.add(function(id,verb,payload){
  ...
  Mashing code
  ...
});

This passes an item id, the verb (update or remove) and the payload. The payload is processed by a Badger.Parser before being sent to the callback. A few are parsers are bundled to give you an idea, but these can easily be customised to suit your needs. Parsers are linked to Badger.Channels. So far there are channels for:

  • Polled Atom feed
  • XMPP Pubsub

However, it's not too tricky to write your own.

We can add multiple channels to our coordinator. Lets see that in action:

var plain = new Badger.Parser.Plain();
var atom_channel = Badger.Channel.Atom({delay: 2000, parser: plain});

badger.backendAppend(atom_channel);

Or we could add a higher priority XMPP channel:

var strophe = ... strophe setup ...
var data_form = new Badger.Parser.DataForm();
var xmpp_channel = new Badger.Channel.XMPP({
  connection: strophe,
  parser:     data_form,
});

badger.backendPrepend(xmpp_channel);

Adding a new channel will cause any failed subscriptions to be retried. Also changing the priority of channels will cause subscriptions to be renegotiated so that the best one is used that works.

Some channels like the Polled Atom feed do not really support push. These channels can have an extra method called hint. This allows hint to be called when you know there is new content available which triggers a check immediately. This means the next schedulded poll does not have to execute before the update can be discovered.

badger.hint("node/i/know/has/been/updated")

Tests

All of the tests are written in Jasmine. Sprockets is used to describe dependencies between the files. To run the tests, you will first need to install Ruby and Bundler. Once you have this:

$ bundle install
$ bundle exec rake jasmine

Open your browser to http://localhost:8888

If you want to run the tests directly in the console just type:

$ bundle exec rake jasmine:ci
/Users/theo/.rvm/rubies/ruby-1.9.3-p0/bin/ruby -S rspec spec/javascripts/support/jasmine_runner.rb --colour --format progress
[2012-03-15 15:46:50] INFO  WEBrick 1.3.1
[2012-03-15 15:46:50] INFO  ruby 1.9.3 (2011-10-30) [x86_64-darwin11.1.0]
[2012-03-15 15:46:50] INFO  WEBrick::HTTPServer#start: pid=39919 port=63714
Waiting for jasmine server on 63714...
jasmine server started.
Waiting for suite to finish in browser ...
..........................................

Or you can check the current status of master using Travis

Building

Provided you have all of the software installed to run the tests (see above). You can build the code using:

$ bundle exec rake build

This will create a copy of the code in the build folder. It will also package up any external dependencies (such as callback-js). If you are already using Sprockets then it is best to copy the src folder to your project and let that deal with the build dependencies (avoids duplication).

TODO

Add support for:

  • socket.io
  • pusher