[Twisted-Python] PB/Remote Object/Deferred question

Peter Westlake peter.westlake at pobox.com
Wed Sep 9 13:35:53 EDT 2009

On Wed, 09 Sep 2009 12:39 -0400, "John Crawford" <cyclops at speakeasy.net>
> I'm trying to understand the Perspective Broker, reading over the 
> on-site documentation, specifically the article:
> http://twistedmatrix.com/projects/core/documentation/howto/pb-usage.html
> and there is a section about the callRemote() function that I really 
> don't understand :)
> First, consider these three lines:
> d = factory.getRootObject()
> d.addCallback(lambda object: object.callRemote("echo", "hello network"))
> d.addCallback(lambda echo: 'server echoed: '+echo)
> Second, the documentation says, "...object.callRemote() returns a 
> Deferred. Assuming the remote method was run without causing an 
> exception (including an attempt to invoke an unknown method), the 
> callback attached to that Deferred will be invoked with any objects 
> that were returned by the remote method call."
> If I read this correctly, callRemote() returns a whole new Deferred 
> object, which is *not* the same as the 'd' Deferred object we already 
> have. So that *new* Deferred should be the one that the next callback 
> (line 3) is added to, since the next callback is based on the success 
> of the callRemote(). So wouldn't these be the correct lines:
> d = factory.getRootObject()
> d2 = d.addCallback(lambda object: object.callRemote("echo", "hello
> network"))
> d2.addCallback(lambda echo: 'server echoed: '+echo)

Can I get in before someone else does? If I do, will I get it right?
Be kind, O wise ones!

Here goes:

d.addCallback always returns d. Remember that the callRemote is only
called once d is fired, so its result and the result of the lambda
expression are (simplifying a little) only computed after this piece
of code is long since over and done with. It just adds callback
functions (your lambda expressions) to the callback chain of d.
The result of each callback function is fed into the callback chain, to
be passed as parameter to the next callback.

Because the return value from the first callback is a Deferred, it is
not passed directly to the next callback. Instead processing pauses
until this new Deferred fires, and then the value it returns is passed
to the echo callback. It's a feature, and a most nifty one :-)

In summary:

factory.getRootObject returns a Deferred, d.

Two callbacks are added to d.

...time passes...

Something in the factory module finishes doing getRootObject
and passes the result ("thing", say) to d: "d.callback(thing)".

The first callback function uses it: "object.callRemote(rootThing)".

callRemote returns a new Deferred, d2.

The code of Deferred.callback spots the callback has returned
a Deferred. It puts d2 aside in a safe place, and d.callback()

...time passes...

The callRemote gets an answer, and d2 fires. It doesn't have
any callbacks (that you know about, at least) so it returns
the value.

The code of Deferred.callback that previously stashed d2
notices that it has fired, picks up the value and passes
it along the next callback in d's chain, the lambda echo.



More information about the Twisted-Python mailing list