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 <exar...@twistedmatrix.com> > On 07:53 pm, wasi...@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@twistedmatrix.com > http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python >
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python