waterwaterwaterwaterwaterwaterwaterwaterwaterwaterPollenation web design
20/05/2005

Setting up a Twisted Deferred Chain

cats:

    We had some code that setup a deffered chain something like this:

    d = deferringFunc1()
    d.addCallback(deferringFunc2)
    d.addCallback(deferringFunc3)
    return d
    

    However, a typo showed up a flaw in this setup. The call to deferringFunc1 starts some async processing that goes off on its merry way in the "background". So far, so good. The problem comes when deferringFunc3 does not exist - a NameError is raised and the deferred, d, is not returned to the calling function.

    We now have two paths of processing: whatever deferringFunc1 started and the error handling in the calling function. Obviously, the idea of the deferred chain was that the caller should wait for the chain to complete (or fail) before continuing.

    A better way to create the deferred chain is:

    # Create a deferred to hang the chain off. Fire it later, when we're ready.
    d = defer.Deferred()
    # Setup the whole chain
    d.addCallback(lambda spam: deferringFunc1())
    d.addCallback(deferringFunc2)
    d.addCallback(deferringFunc3)
    # Start the chain and return.
    d.callback(None)
    return d
    

    This time, we can be sure that deferringFunc1 will not start anything until the whole chain is ready to run. If something goes wrong during setup, i.e. deferringFunc3 still does not exist, then an error is raised and the deferred chain is garbage collected.