[Twisted-Python] Deferreds and Tasklets
So I am still fiddling with interesting ways to combine stackless and twisted. Its fun, but I am probably naively hacking! (I always seem to want to use the deprecated code!- probably says a lot about me?) I'm using Perspective Broker to do remote calls to an app running Twisted-Stackless. PB is positively brilliant, btw. So say the a remote caller wants to get data from my app. It calls remote_GetData() in my PB app, which uses the actor model(each object has a channel.receive() running in its own tasklet). remote_GetData() has to send a message thru a stackless.channel() to get the required data, then it must stackless.schedule() Now it waits for the result to arrive at its own channel.receive(), which then needs to be passed back as the return value of remote_GetData(). Is this possible? Perhaps like this: from twisted.spread import pb from twisted.internet import reactor import stackless dbRx = stackless.channel() pbRx = stackless.channel() class DataSource: def Listen(self): while 1: msg = dbrx.receive() # a channel will arrive here msg.send(42) stackless.schedule() def __init__(self): stackless.tasklet(self.Listen)() class pbBroker(pb.Referenceable): def remote_GetData(self): dbRx.send(pbRx) result = pbRx.receive() # return 42 to remote caller thru pb return result This isn't ideal since I don't want pbBroker to block during the receive. I'd like it to closer resemble the Listen loop of the first class, so other objects can talk to pbBroker while it is waiting. Maybe like this: class pbBroker(pb.Referenceable): def Listen(self): while 1: msg = self.rx.receive() # do stuff with msg from other local objects stackless.schedule() def __init__(self): self.rx = stackless.channel() stackless.tasklet(self.Listen)() def remote_GetData(self): ch = stackless.channel() dbRx.send(ch) # can block since its a dedicated channel result = ch.receive() # return 42 to remote caller thru pb return result I guess the same problem arise when remote_GetData() has to use a deferred too. from twisted.enterprise import adbapi dbPool = adbapi.ConnectionPool("MySQLdb", db="db", user="user", passwd="pw") class pbBroker(pb.Referenceable): def remote_GetDeferredData(self): d = dbPool.runInteraction(DoQuery, "SELECT * FROM users") # DoQuery just wraps a query with try/except d.addCallback(self.GetDeferredData_Success) def GetDeferredData_Success(self, result): # return to remote caller thru pb return result ## WRONG How can I return a value for a remote_* call when I only get that value thru another callback? Sorry its a long and confusing one! Simon -- Linux user #458601 - http://counter.li.org. -- Linux user #458601 - http://counter.li.org.
On Sun, Apr 6, 2008 at 12:42 PM, Simon Pickles <sipickles@hotmail.com> wrote:
So I am still fiddling with interesting ways to combine stackless and twisted. Its fun, but I am probably naively hacking! (I always seem to want to use the deprecated code!- probably says a lot about me?)
I've solved some of these problems in Corotwine, which uses Greenlet. You may want to take a look at least to see how it can be done. Specifically relating to Deferreds, corotwine.defer will probably be helpful. http://launchpad.net/corotwine/ -- Christopher Armstrong International Man of Twistery http://radix.twistedmatrix.com/ http://twistedmatrix.com/ http://canonical.com/
participants (2)
-
Christopher Armstrong -
Simon Pickles