def test_proc_err(self): """Processing function throws exception """ T = proto_helpers.StringTransport() P = MockBLP() P.rx_buf_size = 4 P.makeConnection(T) P.dataReceived('A\nB\nC\n') self.assertEqual(P.lines, ['A', 'B', 'C']) P._finish(err=RuntimeError('oops')) self.assertEqual(T.producerState, 'stopped') P.connectionLost(error.ConnectionClosed()) # connection error will be ignored in favor of proc. error P.connectionLost(failure.Failure(error.ConnectionAborted())) try: yield P.defer self.assertTrue(False) except RuntimeError as e: self.assertEqual(e.message, 'oops') self.alldone = True
def wait_for_message_for_peer(self, inh, prefer_msg_uuid, still_wait_checker, d=None): """Implementation of interface from C{AbstractTransactionManager}. @type inh: AbstractInhabitant @type prefer_msg_uuid: MessageUUID, NoneType @type still_wait_checker: col.Callable @type d: defer.Deferred, NoneType @returns: a deferred that fires with the message, or maybe a {error.ConnectionClosed()}. @rtype: defer.Deferred """ assert not in_main_thread() if d is None: logger.debug('Checking for message for %r', inh) else: logger.debug('1 second passed, polling a message for %r', inh) d = defer.Deferred() if d is None else d if not still_wait_checker(): logger.debug("Seems like we don't need to wait for %r anymore", inh) d.errback(error.ConnectionClosed(u'No need to wait on {!r}' .format(inh))) else: logger.debug("Let's deliver a message for %r, preferrably %r", inh, prefer_msg_uuid) reply_msg = self.deliver_message_for_peer(inh, prefer_msg_uuid) assert isinstance(reply_msg, (AbstractMessage, NoneType)), \ repr(reply_msg) if reply_msg is not None: # We have an outgoing message for inh already! logger.verbose('Going to deliver a message for %r: %r', inh, reply_msg) d.callback(reply_msg) else: # Unfortunately, we don't have a message yet. # Let's recall this function in, say, a second. logger.verbose('No messages for %r, retrying in %r', inh, POLL_FOR_OUTGOING_MESSAGES_PERIOD) callFromThread( task.deferLater, reactor, POLL_FOR_OUTGOING_MESSAGES_PERIOD.total_seconds(), lambda: callInThread( self.__wait_for_message_for_peer_ignore_result, inh, prefer_msg_uuid, still_wait_checker, d)) return d
def connectionLost(self, reason=None): self.setTimeout(None) d, self._negotiation_d = self._negotiation_d, None # the Deferred is only relevant until negotiation finishes, so skip # this if it's already been fired if d: # Each call to loseConnection() sets self._error first, so we can # deliver useful information to the Factory that's waiting on # this (although they'll generally ignore the specific error, # except for logging unexpected ones). The possible cases are: # # cancel: defer.CancelledError # far-end disconnect: BadHandshake("connection lost") # handshake error (something we didn't like): BadHandshake(what) # other error: some other Exception # timeout: BadHandshake("timeout") d.errback(self._error or BadHandshake("connection lost")) if self._consumer_deferred: self._consumer_deferred.errback(error.ConnectionClosed())
def execute(self, req, keyspace=None): if self.my_proto is None: return defer.fail( error.ConnectionClosed( 'Lost connection before %s request could be made' % (req.method, ))) method = getattr(self.my_proto.client, req.method, None) if method is None: raise InvalidThriftRequest("don't understand %s request" % req.method) d = defer.succeed(0) if req.method == 'set_keyspace': newksname = req.args[0] d.addCallback(lambda _: method(newksname)) d.addCallback(self.store_successful_keyspace_set, newksname) else: if keyspace is not None and keyspace != self.keyspace: d.addCallback(lambda _: self.my_set_keyspace(keyspace)) d.addCallback(lambda _: method(*(req.args))) return d
def close(self): self.transport.loseConnection() while self._waiting_reads: d = self._waiting_reads.popleft() d.errback(error.ConnectionClosed())