[Stackless] Stackless + Twisted with deferred operations
Carlos Eduardo de Paula
carlosedp at gmail.com
Tue Mar 13 15:05:10 CET 2007
Hi Greg, great suggestion and fix for it, with your code I improved
the blockOn function and added a timeout feature to it.
def blockOn(d, timeout=999):
"""
Use me in stacklessy-code to wait for a Deferred to fire.
If the result is an failure, send the exception via the channel
to be captured by the tasklet.
The timeout parameter is passed in seconds, defaults to 999 seconds
and returns an exception.
"""
ch = NWChannel()
me = stackless.getcurrent()
def goodCB(r, me, return_channel):
cancelTimeout()
return_channel.send_nowait(r)
# if the deferred is called back immediately, this function
will be called
# from the original tasklet. no need to reschedule.
if stackless.getcurrent() != me:
stackless.schedule()
def badCB(f, me, return_channel):
cancelTimeout()
return_channel.send_exception_nowait(f.type, f.value)
# if the deferred fails immediately, this function will be called
# from the original tasklet. no need to reschedule.
if stackless.getcurrent() != me:
stackless.schedule()
def onTimeout(me, return_channel):
return_channel.send_exception_nowait("TimeoutException",
"Defer Timeout")
if stackless.getcurrent() != me:
stackless.schedule()
def cancelTimeout():
if delayedCall.active():
delayedCall.cancel()
delayedCall = reactor.callLater(timeout, onTimeout, me, ch)
d.addCallback(goodCB, me, ch)
d.addErrback(badCB, me, ch)
return ch.receive()
With this we can have a timeout function to be called... its within
the specifications of Twisted since defer.setTimeout is deprecated.
For my example I do something like this:
try:
reactor.connectTCP("localhost", 8800, factory)
def1 =
factory.login(credentials.UsernamePassword(self.login, self.pwd))
self.perspective = blockOn(def1)
except ConnectionRefusedError, val:
print "Connection could not be opened."
exit()
except "TimeoutException":
print "Timeout exception"
exit()
except:
print "MISC ERROR"
exit()
I will update the examples in the repository, if anyone have any other
improvement just send it out...
Carlos
On 3/12/07, Greg Hazel <greg at bittorrent.com> wrote:
>
> > def blockOn(d):
> > """
> > Use me in stacklessy-code to wait for a Deferred to fire.
> > If the result is an failure, send the exception via the channel
> > to be captured by the tasklet.
> > """
> > ch = stackless.channel()
> > def cbOK(r):
> > ch.send(r)
> > def cbNOK(r):
> > ch.send_exception(r.type, r.value)
> > d.addCallbacks(cbOK, cbNOK)
> > return ch.receive()
>
>
> The problem with this, and the purpose for NWChannel, is that
> d.addCallbacks() could call either of the callbacks immediately, causing a
> block before ch.reveive() is run. Try it: blockOn(defer.succeed(1))
> Using NWChannel, you can make a more robust blockOn like this (with 'good'
> and 'bad' from the example):
>
> def blockOn(df):
> """
> Use me in stacklessy-code to wait for a Deferred to fire.
> If the result is an failure, send the exception via the channel
> to be captured by the tasklet.
> """
> ch = NWChannel()
> me = stackless.getcurrent()
> df.addCallback(good, me, ch)
> df.addErrback(bad, me, ch)
> return ch.receive()
>
> -Greg
_______________________________________________
Stackless mailing list
Stackless at stackless.com
http://www.stackless.com/mailman/listinfo/stackless
More information about the Stackless
mailing list