[Twisted-Python] Using Deferred.called to distinguish between synchronous and asynchronous result

Maciej Wasilak wasilak at gmail.com
Thu Aug 30 15:58:12 EDT 2012


Jean-Paul,

thank you very much for your answer - I would have missed this problem for
sure.
Second option seems a bit more challenging, I'll try this one.

Best Regards
Maciej Wasilak

2012/8/29 <exarkun at twistedmatrix.com>

> On 07:53 pm, wasilak at gmail.com wrote:
> >Hello,
> >
> >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
> >response
> >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
> >(separate
> >response)
> >
> >(I think behavior #1 is called synchronous in most Twisted tutorials,
> >and
> >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
> >would
> >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
> >ACK+Response
> >(that means request handler used defer.succeed() or somethin similar)
> >2. If False I send empty ACK, and wait for callback to send Response
> >
> >code:
> >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
> happened).
>
> Hope this helps,
> Jean-Paul
>
> _______________________________________________
> Twisted-Python mailing list
> Twisted-Python at twistedmatrix.com
> http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://twistedmatrix.com/pipermail/twisted-python/attachments/20120830/696becae/attachment.htm 


More information about the Twisted-Python mailing list