Jean-Paul,<div><br></div><div>thank you very much for your answer - I would have missed this problem for sure. </div><div>Second option seems a bit more challenging, I&#39;ll try this one.</div><div><br></div><div>Best Regards</div>
<div>Maciej Wasilak<br><br><div class="gmail_quote">2012/8/29  <span dir="ltr">&lt;<a href="mailto:exarkun@twistedmatrix.com" target="_blank">exarkun@twistedmatrix.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5">On 07:53 pm, <a href="mailto:wasilak@gmail.com">wasilak@gmail.com</a> wrote:<br>
&gt;Hello,<br>
&gt;<br>
&gt;I am implementing UDP-based protocol in Twisted (CoAP) which allows two<br>
&gt;behaviors when answering requests:<br>
&gt;<br>
&gt;1. If response is immediately available - send acknowledgement and<br>
&gt;response<br>
&gt;in a single datagram (piggyback response)<br>
&gt;2. If response needs to be fetched or prepared - send datagram with<br>
&gt;acknowledgement, and then send another datagram with a response<br>
&gt;(separate<br>
&gt;response)<br>
&gt;<br>
&gt;(I think behavior #1 is called synchronous in most Twisted tutorials,<br>
&gt;and<br>
&gt;behavior #2 is called asynchronous.)<br>
&gt;<br>
&gt;When programmer is implementing his application on top of CoAP<br>
&gt;protocol, he<br>
&gt;or she needs to choose how his request handler is going to behave. I<br>
&gt;would<br>
&gt;like to handle both behaviors in the same manner - by forcing every<br>
&gt;user-written request handler to return Deferred. Then I would<br>
&gt;check Deferred.called parameter.<br>
&gt;1. If True - callback will execute immediately and send proper<br>
&gt;ACK+Response<br>
&gt;(that means request handler used defer.succeed() or somethin similar)<br>
&gt;2. If False I send empty ACK, and wait for callback to send Response<br>
&gt;<br>
&gt;code:<br>
&gt;def respond(request):<br>
&gt;        d = requestHandler(request)<br>
&gt;        if d.called is False:<br>
&gt;            sendEmptyAck()<br>
&gt;        d.addCallback(sendResponse)<br>
&gt;<br>
&gt;I assume that sendResponse can send either ACK+RSP, or only RSP.<br>
&gt;<br>
&gt;I would like to ask if this is a proper approach?<br>
<br>
</div></div>This isn&#39;t the right way to go.  The `called` attribute is set to `True`<br>
as soon as `Deferred.callback` is called.  This might sound like it&#39;s<br>
what you want, but only if you disregard the chaining feature of<br>
Deferreds, where a callback on the Deferred might return a *new* unfired<br>
Deferred.  Now your original Deferred has `called` set to `True` but you<br>
don&#39;t actually have a result yet.<br>
<br>
Instead, there are two obvious options:<br>
<br>
  1. Allow the application to return a non-Deferred result.  Use<br>
`isinstance` to detect this case and do the synchronous send when you<br>
see a non-Deferred come back.  Send the empty ACK and ultimately the<br>
result in the other case.<br>
<br>
  2. Change your empty ACK logic to be time-based instead.  Say, if the<br>
application doesn&#39;t produce a result within 10 milliseconds, send the<br>
empty ACK.  Implement this using `reactor.callLater` and<br>
`IDelayedCall.cancel`.  You&#39;ll set up a delayed call to send the empty<br>
ACK every time you call application code, but in the callback on the<br>
application&#39;s Deferred, you&#39;ll cancel that call (unless it has already<br>
happened).<br>
<br>
Hope this helps,<br>
Jean-Paul<br>
<br>
_______________________________________________<br>
Twisted-Python mailing list<br>
<a href="mailto:Twisted-Python@twistedmatrix.com">Twisted-Python@twistedmatrix.com</a><br>
<a href="http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python" target="_blank">http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python</a><br>
</blockquote></div><br></div>