[Twisted-Python] Using Deferred.called to distinguish between synchronous and asynchronous result
wasilak at gmail.com
Thu Aug 30 15:58:12 EDT 2012
thank you very much for your answer - I would have missed this problem for
Second option seems a bit more challenging, I'll try this one.
2012/8/29 <exarkun at twistedmatrix.com>
> On 07:53 pm, wasilak at gmail.com wrote:
> >I am implementing UDP-based protocol in Twisted (CoAP) which allows two
> >behaviors when answering requests:
> >1. If response is immediately available - send acknowledgement and
> >in a single datagram (piggyback response)
> >2. If response needs to be fetched or prepared - send datagram with
> >acknowledgement, and then send another datagram with a response
> >(I think behavior #1 is called synchronous in most Twisted tutorials,
> >behavior #2 is called asynchronous.)
> >When programmer is implementing his application on top of CoAP
> >protocol, he
> >or she needs to choose how his request handler is going to behave. I
> >like to handle both behaviors in the same manner - by forcing every
> >user-written request handler to return Deferred. Then I would
> >check Deferred.called parameter.
> >1. If True - callback will execute immediately and send proper
> >(that means request handler used defer.succeed() or somethin similar)
> >2. If False I send empty ACK, and wait for callback to send Response
> >def respond(request):
> > d = requestHandler(request)
> > if d.called is False:
> > sendEmptyAck()
> > d.addCallback(sendResponse)
> >I assume that sendResponse can send either ACK+RSP, or only RSP.
> >I would like to ask if this is a proper approach?
> This isn't the right way to go. The `called` attribute is set to `True`
> as soon as `Deferred.callback` is called. This might sound like it's
> what you want, but only if you disregard the chaining feature of
> Deferreds, where a callback on the Deferred might return a *new* unfired
> Deferred. Now your original Deferred has `called` set to `True` but you
> don't actually have a result yet.
> Instead, there are two obvious options:
> 1. Allow the application to return a non-Deferred result. Use
> `isinstance` to detect this case and do the synchronous send when you
> see a non-Deferred come back. Send the empty ACK and ultimately the
> result in the other case.
> 2. Change your empty ACK logic to be time-based instead. Say, if the
> application doesn't produce a result within 10 milliseconds, send the
> empty ACK. Implement this using `reactor.callLater` and
> `IDelayedCall.cancel`. You'll set up a delayed call to send the empty
> ACK every time you call application code, but in the callback on the
> application's Deferred, you'll cancel that call (unless it has already
> Hope this helps,
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Twisted-Python