Wednesday, February 10, 2010

gen_client in action: fixing temporary subscriptions

In this post I'd like to discuss one particular pubsub challenge, namely temporary subscriptions. I will also use this discussion as an opportunity to show some gen_client code that was written in order to deal with this challenge.

Let's assume we have a web-based XMPP weather service available for free public access, so everyone can come to our site, choose places and watch weather data updated in real-time. This is what pubsub is designed for: data streams being publishers, the clients being subscribers; each data stream will publish to its respective node, and the clients will subscribe to nodes they are interested in. Now comes interesting part: we expect significant number of clients to come use our service, so  we don't want to create accounts for each client. Instead clients will be automatically signed in with some shared account and assigned random resource name. XEP-0060 allows subscriptions based on full JIDs, so each client will still have its own subscriptions. However, using random resource names  impose having temporary subscriptions, because the moment client signs out, the resource name he was using becomes unusable, and so do subscriptions.

So how do we deal wth temporary subscriptions? XEP-0060 (1.13rc13, p. 12.4) describes how it should be: once subscriber goes offline, the temporary subscription gets canceled. Unfortunately, it looks like ejabberd (v. 2.1.2 at the time of writing)  doesn't yet have it working, at least I was unable to configure temporary subscriptions the way XEP-0060 suggests. This means that once resource is gone, its subscriptions are still hanging around. Bad (very bad) thing about  it, not to mention excessive memory consumption, is that ejabberd will push data meant for these orphaned subscriptions to the resources of the same account that are still online. This will be an absolute mess - even if your client code is smart enough to filter foreign subscriptions (possibly by matching subscription identifiers), the enormous traffic will be generated pretty soon. Remember, we have a single shared account for all our clients.  Conclusion: we absolutely have to find the way to get rid of orphaned subscriptions.

Here is a source code of the bot (using gen_client) that supports temporary subscriptions by monitoring resources and getting rid of subscriptions at the moment resource they belong to goes offline. Additionally, it cleans up such subscriptions on a startup.  I'm planning to do code walk-through and explain gen_client capabilities shown in the code in one of posts following shortly.

This is, of course, a temporary solution and should only be used if your XMPP server doesn't support temporary subscriptions.

I still have a feeling that there might be an easier solution, but I haven't found any practical cases of using temporary subscriptions, so if anyone has related experience, please come forward and share it here.