Ejemplo n.º 1
0
    def get_message(self, correlation_id):

        try:
            while correlation_id not in self.replies:
                self.consumer.channel.connection.client.drain_events(
                    timeout=self.timeout)

            body, message = self.replies.pop(correlation_id)
            self.provider.handle_message(body, message)

        except socket.timeout:
            timeout_error = RpcTimeout(self.timeout)
            event = self.provider._reply_events.pop(correlation_id)
            event.send_exception(timeout_error)

            # timeout is implemented using socket timeout, so when it
            # fires the connection is closed, causing the reply queue
            # to be deleted
            self._setup_consumer()

        except (IOError, ConnectionError) as exc:
            for event in self.provider._reply_events.values():
                rpc_connection_error = RpcConnectionError(
                    'Disconnected while waiting for reply: %s', exc)
                event.send_exception(rpc_connection_error)
            self.provider._reply_events.clear()
            # In case this was a temporary error, attempt to reconnect. If
            # we fail, the connection error will bubble.
            self._setup_consumer()

        except KeyboardInterrupt as exc:
            event = self.provider._reply_events.pop(correlation_id)
            event.send_exception(exc)
            # exception may have killed the connection
            self._setup_consumer()
Ejemplo n.º 2
0
 def on_consume_ready(self):
     # This is called on re-connection, and is the best hook for detecting
     # disconnections. If we have any pending reply events, we were
     # disconnected, and may have lost replies (since reply queues auto
     # delete).
     for event in self._reply_events.values():
         event.send_exception(
             RpcConnectionError('Disconnected while waiting for reply'))
     self._reply_events.clear()
Ejemplo n.º 3
0
    def test_wait_already_disconnected(self, queue_consumer):
        correlation_id = 1
        event = ConsumeEvent(queue_consumer, correlation_id)

        exc = RpcConnectionError()

        event.send_exception(exc)
        with pytest.raises(RpcConnectionError):
            event.wait()
        assert not queue_consumer.get_message.called
Ejemplo n.º 4
0
    def _poll_messages(self):
        replies = {}

        correlation_id = yield

        while True:
            try:
                for body, msg in queue_iterator(self.queue,
                                                timeout=self.timeout):
                    msg_correlation_id = msg.properties.get('correlation_id')

                    if msg_correlation_id not in self.provider._reply_events:
                        _logger.debug("Unknown correlation id: %s",
                                      msg_correlation_id)
                        continue

                    replies[msg_correlation_id] = (body, msg)

                    # Here, and every time we re-enter this coroutine (at the
                    # `yield` statement below) we check if we already have the
                    # data for the new correlation_id before polling for new
                    # messages.
                    while correlation_id in replies:
                        body, msg = replies.pop(correlation_id)
                        self.provider.handle_message(body, msg)
                        correlation_id = yield

            except RpcTimeout as exc:
                event = self.provider._reply_events.pop(correlation_id)
                event.send_exception(exc)

                # timeout is implemented using socket timeout, so when it
                # fires the connection is closed, causing the reply queue
                # to be deleted
                self._setup_queue()
                correlation_id = yield

            except ConnectionError as exc:
                for event in self.provider._reply_events.values():
                    rpc_connection_error = RpcConnectionError(
                        'Disconnected while waiting for reply: %s', exc)
                    event.send_exception(rpc_connection_error)
                self.provider._reply_events.clear()
                # In case this was a temporary error, attempt to reconnect. If
                # we fail, the connection error will bubble.
                self._setup_queue()
                correlation_id = yield

            except KeyboardInterrupt as exc:
                event = self.provider._reply_events.pop(correlation_id)
                event.send_exception(exc)
                # exception may have killed the connection
                self._setup_queue()
                correlation_id = yield
Ejemplo n.º 5
0
    def test_wait_disconnected_while_waiting(self, queue_consumer):
        correlation_id = 1
        event = ConsumeEvent(queue_consumer, correlation_id)

        exc = RpcConnectionError()

        def get_message(correlation_id):
            event.send_exception(exc)

        queue_consumer.get_message.side_effect = get_message

        with pytest.raises(RpcConnectionError):
            event.wait()
        assert queue_consumer.get_message.call_args == call(correlation_id)