pubsub.ik.nu uses Idavoll 2
As of today, the pubsub service
        at ik.nu is
        powered by Idavoll
          2. This means that I think the Twisted rewrite of
        Idavoll is now good enough to support Mimír and the pubsub features of
        this site. A nice milestone.
The current implementation has two different backends, one that
        stores all data in memory, and one that has persistent storage using
        PostgreSQL. I use the
        latter for pubsub.ik.nu. This backend is very
        limited at the moment. It only supports publishing items, storing the
        items (if the node is so configured) and notifying subscribers.
        Creating nodes, setting up subscriptions and configuration of nodes is
        done by updating the database. But that should change soon
        enough.
I am now at a point that the basic architecture of Idavoll is becoming stable enough to quickly implement new features. I have struggled a bit with finding out how to best use interfaces and adapters in Twisted, and spiv, on the #twisted IRC channel helped me go in the right direction.
The easy part was this: I splitted up the (optional) features of
        JEP-0060 in nice chunks that are represented in several backend service
        interfaces. That way, people can code backends with different storage
        mechanisms and/or business rules, while only having to implement the
        parts that are useful for the application at hand. So, there is one
        interface for publishing items (IPublishService),
        one for subscribing to, and unsubscribing from, a node
        (ISubscriptionService), and so on.
Next, I wanted to split up the Jabber protocol implementation along
        similar lines. These would be implemented as adapters from such a
        backend service interface to the
        twisted.protocol.jabber.component.IService interface
        for implementing subservices of a Jabber server component. The problem
        with this is that you would want to have one backend class implement
        the choosen interfaces and then instantiate a
        component.IService with an instance of that backend
        class. And you can't do that, because it is ambigious!
Taking the two interfaces described above. Suppose I implement a
        backend (BackendService) that implements
        IPublishService and
        ISubscriptionService, and I have adapters to
        component.IService for both of them. What does the following do?
import my_backend
import pubsub
from twisted.protocols.jabber import component
... 
backend = my_backend.BackendService()
service = component.IService(backend)
...
        
      As I said, this is ambigious. This could yield either adapter
        for the implemented backend interfaces. So, what I did was
        still implement the code for the backend in one class that is
        MultiService, and have skeleton child services that state the actual
        interface that is implemented and pass on the method calls to their
        parent. That way, you can simply call for the adapter from these
        child service to component.IService, resulting
        in a component.Service for each backend
        service.
This probably isn't going to win any beauty contests, but it
        was the result of my discussion with spiv. Other approaches were
        even less desirable. I could define all adapters to be incremental
        and have only one component.Service per specific
        backend. Another approach would be to have some code that figures out
        which adapters to fire up from the __implements__
        attribute of the backend. I didn't want to go there.
Have a look at the code in the Idavoll CVS repository or the generated API documentation. If you have any questions, comments or suggestions, let me know!