Orbited
SitePen Support

PubSub and Topics

by Dylan SchiemannOctober 26th, 2007

Comet servers and clients make frequent use of PubSub and topics. PubSub, an abbreviation for publish and subscribe, is an asynchronous messaging paradigm found in distributed event handling systems. Topics are useful in a number of cases. The most common use is when you have a number of different objects that all want to broadcast their changes to a number of other interested parties that are listening for changes.

Unlike traditional event registry systems where an event handler is explicitly registered to an event source, subscribers in a PubSub system only declare an interest in messages of a particular class, with no knowledge of the publisher of an event. This declaration of interest occurs through registering a handle to a topic. The simple example that I used in my introduction to PubSub explains this concept more clearly:

dojox.cometd.subscribe("/the/channel", object, "function");
dojox.cometd.publish("/the/channel", {object: "JSON encoded data"});

In both the publish and subscribe examples shown above, there is a topic identified by the string “/the/channel”. Implementations such as mod_pubsub treat topics as paths where “/the” would be a parent topic to “/the/channel”, whereas implementations such as the client-side Dojo Toolkit consider topics to be pure strings with no interpretation of the implied hierarchy.

Topics are not limited to Comet implementations. For example, with Dojo, client-side events can be routed with the use of topics. This is particularly useful in user interface development when a many-to-many event registration system is needed. Not surprisingly, the API is similar to the Cometd client:

dojo.subscribe(topic, context, method);
dojo.publish(topic, args);

or

dojo.subscribe("/the/channel", object, "function");
dojo.publish("/the/channel", {object: "JSON encoded data"});

The most significant difference between Dojo’s topic system and that found in Cometd is that Cometd’s publishes and subscribes over Bayeux to a Comet server. Also of note, Cometd and mod_pubsub treat topics as paths, implying parent and child relationships between topics. This is particularly useful in implementing permissions models. For example, a publisher to a parent topic might be granted rights to publish to a child topic, or a subscriber to a parent topic might elect to receive all messages to all child topics.

Topics are highly useful on the client- and server-side for event driven applications. So, how do you implement a topic system? Let’s start by taking a look at the Dojo source, first by looking inside dojo/_base/connect.js

First, we see an empty object that will store a collection of topics:

dojo._topics = {};

Then, we find an interface for subscribe:

dojo.subscribe = function(topic, context, method){
        return [topic, dojo._listener.add(dojo._topics, topic,
                dojo.hitch(context, method))];
}

dojo.hitch helps preserve scope. There’s also a call to the private method dojo._listener.add:

add: function(source, method, listener){
	source = source || dojo.global;
	var f = source[method];
	if(!f || !f._listeners){
		var d = dojo._listener.getDispatcher();
		d.target = f;
		d._listeners = [];
		f = source[method] = d;
	}
	return f._listeners.push(listener);
}

The first block checks to see if there is already a registered instance of the method on the source topic—in other words, is there already a subscriber object? If not, a new listener object is instantiated:

getDispatcher: function(){
	return function(){
		var ap=Array.prototype, c=arguments.callee,
			ls=c._listeners, t=c.target;
		var r=t && t.apply(this, arguments);
		for(var i in ls){
			if(!(i in ap)){
				ls[i].apply(this, arguments);
			}
		}
		return r;
	}
}

So now that we have something listening for messages on a topic, we can simply publish to a topic:

dojo.publish = function(topic, args){
	var f = dojo._topics[topic];
	if(f){
		f.apply(this, args||[]);
	}
}

And that’s it. What about in Python? If we take a look at cometd.py

def subscribe(self, request, message):
	client = self.clients[message["clientId"]]

	self._subscribe(client, message["subscription"])
	resp = {
		“timestamp”:	getTimestamp(),
		“channel”:	“/meta/subscribe”,
		“subscription”:	message["channel"],
		“successful”:	True
	}

	client.connection.deliver(resp)
	return { “success”: True }

Removing some basic validation, we see that there is a call to the private _subscribe method, and then a response is delivered for a successful subscription request.

def _subscribe(self, client, chan):
	cparts = chan.split("/")[1:]
	root = self.subscriptions
	if not chan in root:
		root[chan] = weakref.WeakValueDictionary()
		root[chan][client.id] = client

We simply split up the channel by paths, and register a client to the desired channel. Then, when an event is to be routed to a subscriber:

def route(self, request, message):
	root = self.subscriptions
	if root.has_key(message["channel"]):
		subs = root[message["channel"]]
		for client in subs:
			subs[client].connection.deliver(message)
	return { “success”: True }

We simply deliver a message to the connection for each registered client listening to that channel.

Topics provide significant event-driven flexibility packed into very concise code fragments. For additional information, Wikipedia has introductions to PubSub, Event Driven Programming, and the Observer pattern.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]
SitePen, Inc. Comet Services

12 Responses to “PubSub and Topics”

  1. Comet Daily » Blog Archive » Introduction to Bayuex Says:

    [...] project is developing Bayuex, “a protocol for routing events between clients and servers in a publish subscribe [...]

  2. Comet Daily » Blog Archive » A Taxonomy of Event- and REST-based Comet Says:

    [...] about the meaning of the messages. One of the most common forms of event messaging is the publish/subscribe mechanism based on channels, in which agents can subscribe to channels and publish events to [...]

  3. Comet Daily » Blog Archive » Deferreds Says:

    [...] The full source for Dojo.Deferred is well-documented and explains in great detail how to get the most out of this powerful asynchronous programming pattern, making it very suitable for Comet and Ajax client development, as well as pubsub topic systems. [...]

  4. SitePen Blog Blog » Improving Component Communication with the Dojo Toolkit Says:

    [...] would not be the best solution here. What we can do is write two lines with Dojo’s pub/sub system, a reliable solution to JavaScript’s lack of any kind of delegation or watcher system. [...]

  5. Comet Daily » Blog Archive » Cross Frame Communication: Another Comet Application Says:

    [...] URL changes to receive messages. This approach will be used by the OpenAjax hub 1.1 to facilitate pub/sub messaging across frames. Another library was just released that uses an approach which involves loading a [...]

  6. Comet Daily » Blog Archive » Pub/Sub’s relationship with REST and RPC Says:

    [...] blogged about the relationship between REST and RPC. REST and RPC also have a relationship with the publish and subscribe architecture. Joe Walker recently discussed three major API styles for Comet: traditional, [...]

  7. Comet Daily » Blog Archive » Multiple Pub/Sub Brokers Says:

    [...] Pub/sub is a popular architecture for Comet development. Simple applications may only need to deal with a single pub/sub broker (also known as a hub, which can run on a client or a server) [...]

  8. Comet Daily » Blog Archive » Introducing HTTP Channels Says:

    [...] strong coherency and interoperability with publish and subscribe architectures by equating the PubSub concept of a topic or channel with the REST concept of a resource locator. This allows HTTP [...]

  9. Comet Daily » Blog Archive » The Many Shades of Bayeux/Cometd Says:

    [...] Bayeux is a publish/subscribe messaging system, and this has drawn some criticism that PubSub is not the most flexible paradigm for an Ajax/Comet transport. This article attempts to address [...]

  10. Comet Daily » Blog Archive » Using Bayeux with Persevere Says:

    [...] Comet communication can be used to route messages through Persevere’s stored objects. The PubSub system provided by Bayeux is powerful paradigm for building Comet applications, but often [...]

  11. SitePen Blog » When to Use Persevere: a Comparison with CouchDB and Others Says:

    [...] of method call can serve as event for broadcast to clients. Persevere also supports Bayeux and its PubSub system. These Comet capabilities are exclusive to Persevere, and CouchDB has nothing that is [...]

  12. P G Patrudu Says:

    I have a problem with dojo.
    If multiple clients publish simultaneously, the recepient is getting just one of the msgs, and loosing the other.

    Javascript is single-threaded;
    There is nothing obvious in dojo-cometd about this.
    How can the messages be delivered?

    Please suggest a solution.

Leave a Reply



Copyright 2014 Comet Daily, LLC. All Rights Reserved