[Twisted-Python] Deferreds and Tasklets

Simon Pickles sipickles at hotmail.com
Sun Apr 6 10:42:02 MDT 2008


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.







More information about the Twisted-Python mailing list