[Twisted-Python] Adding callback to a Deferred that's already running?

Steve Freitas sflist at ihonk.com
Thu Aug 26 11:07:25 EDT 2004


> This wasn't spectacularly obvious to me the first time either, but I 
> think it's covered somewhere in the deferred execution howto

Ah ha! I think I figured it out. If I do this, it seems to work...

class XMLRPCResponseClass():
    def step1(self):
        self.d = self.db.runQuery(blah)
        self.d.addCallback(self.step2)
        return self.d

    def step2(self, query): # Here's where the change is
        if query == 'yadda':
          return 'This bit works'
        else:
          self.d = self.db.runOperation(blah) # Rebinding self.d to new
                                              # Deferred()
          self.d.addCallback(self.step3) # add callbacks to new one
          return self.d # And return ref to the new one
            
    def step3(self, data):
        return 'Now it gets here!'

The trick is that I need to add any subsequent callbacks to a new
deferred which I return from the function. Strangely (to me), if I try
using chainDeferred() instead of returning the new deferred from step2,
it fails with AlreadyCalled, which I don't yet understand, but that's
fine, 'cause this seems to work well enough.

I really like this technique because I don't have to use a big state
machine at the root level of the xmlrpc calls, or preassign possibly
unnecessary callbacks, or toss around callables as variables until I'm
thoroughly confused. Instead, it allows me to place all the
(client||server) state information for a given method call inside a
class instance which persists only until the xmlrpc method returns. And
multiple calls to this method while it's being simultaneously Deferred()
for other clients don't require any extra coding to handle, as I've got
one class instance per connection. Very clean, very well separated,
which is hard to figure out how to do with this wonderful framework.
Alright, I'll stop ranting now. :-) I still have to give this thing a
workout to make sure it does all I want it to.

Thanks for the help!

Steve





More information about the Twisted-Python mailing list