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'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"><<a href="mailto:exarkun@twistedmatrix.com" target="_blank">exarkun@twistedmatrix.com</a>></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>
>Hello,<br>
><br>
>I am implementing UDP-based protocol in Twisted (CoAP) which allows two<br>
>behaviors when answering requests:<br>
><br>
>1. If response is immediately available - send acknowledgement and<br>
>response<br>
>in a single datagram (piggyback response)<br>
>2. If response needs to be fetched or prepared - send datagram with<br>
>acknowledgement, and then send another datagram with a response<br>
>(separate<br>
>response)<br>
><br>
>(I think behavior #1 is called synchronous in most Twisted tutorials,<br>
>and<br>
>behavior #2 is called asynchronous.)<br>
><br>
>When programmer is implementing his application on top of CoAP<br>
>protocol, he<br>
>or she needs to choose how his request handler is going to behave. I<br>
>would<br>
>like to handle both behaviors in the same manner - by forcing every<br>
>user-written request handler to return Deferred. Then I would<br>
>check Deferred.called parameter.<br>
>1. If True - callback will execute immediately and send proper<br>
>ACK+Response<br>
>(that means request handler used defer.succeed() or somethin similar)<br>
>2. If False I send empty ACK, and wait for callback to send Response<br>
><br>
>code:<br>
>def respond(request):<br>
> d = requestHandler(request)<br>
> if d.called is False:<br>
> sendEmptyAck()<br>
> d.addCallback(sendResponse)<br>
><br>
>I assume that sendResponse can send either ACK+RSP, or only RSP.<br>
><br>
>I would like to ask if this is a proper approach?<br>
<br>
</div></div>This isn'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'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'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't produce a result within 10 milliseconds, send the<br>
empty ACK. Implement this using `reactor.callLater` and<br>
`IDelayedCall.cancel`. You'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's Deferred, you'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>