PubSub Ahoy!
I’ve just found out about
x60br through an
obscure link trek from a blog post in my feed reader. x60br is an XMPP
PubSub library for Python, similar to the one I’m writing. This is teh
awesome, since it means I can check what I’m doing against someone else,
and possibly look into using their implementation in some
areas.
The main difference between the two (apart from the
API, since mine needs to actually work before I can give it a proper API
:P ) is that they handle the asynchronous nature of XMPP
differently.
In order to understand this you’ll need to know
a little about synchronous vs. asynchronous programming, which I’ve
touched on before. The bits of programs which do the most work are
functions. The purpose of a function is to define how to do something so
that you can do it later on, for instance saying “this is how to get the
items from a PubSub node” then later, when you want to get the items at
a node, you can just say “get the items here” rather than having to
recite every step again and again.
In the example I just gave
it could be done in two ways, synchronously or asynchronously. If it
were done synchronously your program would say something
like:
def get_items(server, node):
items =
[]
ask_for_items(server, node)
reply =
None
while reply is
None:
process_replies()
for item in
reply:
items.append(item)
return
items
my_blog_posts = get_items(“pubsub.jabber.org”,
“seriously-this-is-not-worth-reading”)
The first part DEFINES
how to get the items at a node (nothing is run, it is simply a
definition of what getting items means). When the last line is reached
the program will request the items from the server
“http://pubsub.jabber.org”, then will wait for replies until it gets one
and finally put every item it finds into my_blog_posts. Then the next
line is run. This is a REALLY bad way of doing things in any kind of
interactive, GUI-based program, since the whole program will appear to
freeze whilst the reply is being waited for.
The way around
this is to make the function asynchronous. This is more complicated than
the above way of doing things, but it means that your program can get on
with doing other stuff (like updating progress bars, for example) whilst
the routers, ISPs and servers go about sending messages to and fro so
you can get the items. The way I have implemented this in my library
works a little like the following:
def get_items(server,
node, completed_function):
stanza_id = ask_for_items(server,
node)
assign_handler(stanza_id,
completed_function)
def
assign_blog_posts(items):
my_blog_posts =
items
get_items(“pubsub.jabber.org”,
“seriously-this-is-not-worth-reading”,
assign_blog_posts)
This is in a simplified form (since
namespaces aren’t dealt with, some functions aren’t defined and the
reply handling mechanism isn’t shown) but it gets the point across. What
happens is that the request for items is still sent, but instead of
waiting around for a reply before doing anything else, the program just
gets on with things. When a reply IS received, the function
assign_blog_posts is run, which does whatever needs to be done with the
items. This is called a handler function (since it handles the
replies).
The way x60br does things is in a slightly
different way. It uses the following technique:
def
get_items(server, node):
items = ask_for_items(server,
node)
return items
my_blog_posts =
get_items(“pubsub.jabber.org”,
“seriously-this-is-not-worth-reading”)
This looks the same as
the synchronous way, and it is, except that it uses some clever
behind-the-scenes stuff in functions like ask_for_items which makes
my_blog_post get assigned straight away, letting the program carry on,
except instead of assigning the items to my_blog_posts it essentially
assigns a dummy. When the replies are received any instances of this
dummy are changed to the actual items. This is done using the famous
Twisted framework for Python.
These are two ways of
approaching the same problem (one triggers a response, one hands around
an IOU), so I’ll have a go at using x60br (although Twisted really seems
more web servery, rather than desktop applicationy). I’ll use x60br’s
API when modelling my own library’s though, at least as a guide.