On 3/10/06, Tim Allen <screwtape@froup.com> wrote:
On 11 Mar 2006, at 15:44, Brian Granger wrote:
Here is a typical (madeup) usage case:
a = TwistedEnabledObject() a.connect(addr) # This uses reactor.connectTCP to connect to a server myresult = a.computeSomethingUsingTwisted(args) # This should block!!! ...and maybe... y = f(myresult) plot(y)
The key point is that the user will want to direclty use myresult interactively. Also they won't know ahead of time what actions they will want to do. Anyone who has used Matlab or Mathematica (scientists) will find this way of working extremely familiar. There is simply no way that users will want to get a Deferred() and add callbacks to trigger actions. Thus I would argue that I DO want to make my properly written asynchronous code blocking.
It sounds like this is a user-interface problem rather than a software-design problem. A common tool for solving such problems is to ask, "What does other, similar software do?".
It occurs to me that the problem you're facing is not unlike, oh, job- control in bash or zsh. I'd imagine a usage case that looks something like this:
I agree that it is a user interface question. Other software along these lines, like Mathematica and Matlab are fully blocking. Personally, I think this is too restrictive. For the cases you bring up, where the computeSomethingUsingTwisted() method could take a long time it completely makes sense to have something like a job control interface. In fact, we are building this design pattern into our UI where appropriate. But, in many cases, the computeSomethingUsingTwisted() doesn't take long at all. An example of this would be probing the status of the remote server or a trivial computation that a server has relevant data for. In these cases, the result is available nearly instantly (faster then the user could detect, like 1 ms) and it is silly to have a job interface. You simply want the result directly. In our system, we can easily imagine a user making dozens of interactive calls like this over short periods of time. When all of these results are available essentially immediately, it iseems like overkill to have a more complicated UI. But, it is very appropriate to use Twisted underneath, because it really is an asynchronous system and all the error detection and handling is best dealt with that asynchronously. But as long as there are no errors, I woult like the Twisted machinery to just pass along the result directly.
a = TwistedEnabledObject() a.connect(addr) [1] TwistedEnabledObject.connect(self, addr) [1] done TwistedEnabledObject.connect(self, addr) result1 = a.computeSomethingUsingTwisted(args) [1] TwistedEnabledObject.computeSomethingUsingTwisted(args) result2 = a.computeSomeOtherThingUsingTwisted(args) [2] TwistedEnabledObject.computeSomeOtherThingUsingTwisted(args) print 1+3 4 jobs() [1] running TwistedEnabledObject.computeSomethingUsingTwisted(args) [2] running TwistedEnabledObject.computeSomeOtherThingUsingTwisted(args) print repr(result1) <deferredResult (waiting for result)> [1] done TwistedEnabledObject.computeSomethingUsingTwisted(args) print repr(result1) <deferredResult with value: 42> print result.value 42
I think I'd appreciate an environment like that more than an environment that made me wait for things all the time. I don't know if it's possible to achieve with your PyCrust/Twisted hybrid, of course.
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
-- Brian Granger Santa Clara University ellisonbg@gmail.com