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