[Twisted-Python] Dealing with an intermittent PB server

Phil Mayers p.mayers at imperial.ac.uk
Wed Feb 16 20:05:22 EST 2005


On Wed, Feb 16, 2005 at 04:28:32AM +0000, Jp Calderone wrote:
>On Tue, 15 Feb 2005 19:56:15 -0800, Dave Cook <daverz at gmail.com> wrote:
>>I'm rendering the results of a remote method call:
>> 
>>     def data_tableList(self, ctx, data):
>>         ...
>>         d =   self.pbClientFactory.login(creds)
>>         d.addCallback(lambda object: object.callRemote("foo"))
>>         return d
>
>  Always always always use errbacks.  *Especially* for Deferreds that can 
>fail due to transient network conditions.

See, that depends. I ran into this just today in fact, and found that if 
the server has gone away, then you'll get an exception *right then*, not 
via the errback:

def do_stop(self):
  try:
    self.root.callRemote('stop', self).addCallbacks(self.stop, self.err)
  except pb.DeadReferenceError, re:
    self.stale()

Why, why, why why why doesn't the DeadReferenceError go down the 
errback? As it is, the code has to be littered with both synchronous and 
asynchronous error handling, which is needlessly irritating, surely?

The original poster may find his problem was a DeadReferenceError that's 
getting silently eaten (or just not GCed right away) by the framework, 
as I did.

For the original poster, here's what I've got:

class Thing:
  def __init__(self):
    self.root = None
    self.connect()
    
  def connect(self):
    f = pb.PBClientFactory()
    reactor.connectTCP(host, port, f)
    f.getRootObject().addCallbacks(self.connect_ok, self.connect_fail)

  def connect_ok(self, root):
    self.root = root

  def connect_fail(self, f):
    self.banner(f.getErrorMessage())
    reactor.callLater(1, self.connect)

  def stale(self):
    self.root = None
    self.connect()

  def start(self):
    if not self.root:
      self.banner("Connection in progress, please wait")
      return

    try:
      self.root.callRemote('start').addCallbacks(self.start2, self.err)
      self.banner("sent...")
    except pb.DeadReferenceError, re:
      self.stale()
      self.banner("Connection dropped, reconnecting")

  def start2(self, dummy):
    self.banner("started")

  def err(self, f):
    self.banner(f.getErrorMessage())





More information about the Twisted-Python mailing list