
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