Twisted deferred not callable after connection failure
Question
Having my client factory here:
import logging, traceback
from twisted.internet.protocol import ClientFactory
from twisted.internet import defer, reactor, ssl
from twisted.application import service
from protocols.smpp.protocol import SMPPClientProtocol
class SMPPClientFactory(ClientFactory):
protocol = SMPPClientProtocol
def __init__(self, config):
self.config = config
def getConfig(self):
return self.config
def clientConnectionFailed(self, connector, reason):
print "clientConnectionFailed"
self.connectDeferred.errback(reason)
def clientConnectionLost(self, connector, reason):
print "clientConnectionLost"
def connect(self):
self.connectDeferred = defer.Deferred()
factory = SMPPClientFactory(self.config, self.msgHandler)
self.log.warning('Establishing TCP connection to %s:%d' % (self.config.host, self.config.port))
reactor.connectTCP(self.config.host, self.config.port, factory)
return self.connectDeferred
And it's launching code here:
import logging, traceback
from twisted.internet import reactor, defer
from protocols.smpp.configs import SMPPClientConfig
from protocols.smpp.smpp_operations import SMPPOperationFactory
from testbed.client import SMPPClientFactory
class SMPP(object):
def __init__(self, config=None):
if config is None:
config = SMPPClientConfig()
self.config = config
self.opFactory = SMPPOperationFactory(config)
def run(self):
try:
#Bind
SMPPClientFactory(self.config, self.handleMsg).connect().addErrback(self.connectFailed)
except Exception, e:
print "ERROR: %s" % str(e)
def connectFailed(self, reason):
print "Connection failed %s" % str(reason)
def handleMsg(self, smpp, pdu):
pass
if __name__ == '__main__':
config = SMPPClientConfig(host='127.0.0.1', port=2775, username='smppclient1', password='password',
log_level=logging.DEBUG)
logging.basicConfig(level=config.log_level, filename=config.log_file, format=config.log_format,datefmt=config.log_dateformat)
SMPP(config).run()
reactor.run()
When the connection is failing (the remote server is down), i get factory's clientConnectionFailed called but it is strangely getting a "exceptions.AttributeError: SMPPClientFactory instance has no attribute 'connectDeferred'".
I need to call the errback when the connection fails, it seems there's something missing when dealing with deferreds ..
Solution
On your launch code, you instantiated an SMPPClientFactory and called connect() on it. This particular instance will have the connectDeferred attribute. However, connect also instantiated another SMPPClientFactory: factory = SMPPClientFactory(self.config, self.msgHandler)
and this is the instance you used to create the actual connection. This doesn't have the connectDeferred attribute because with this instance connect has never been called.