Example #1
0
 def test_connection_error_with_pika_exception_as_error(self):
     """Assert callback is called on connection error."""
     connection = "test_connection"
     error_message = "test_err_msg"
     mock_connection = mock.Mock()
     self.consumer._connection = mock_connection
     with mock.patch("fedora_messaging._session._log") as mock_log:
         self.consumer._on_connection_error(
             connection, pika_errs.AMQPConnectionError(error_message))
     mock_connection.ioloop.call_later.assert_called_once_with(
         1, self.consumer.reconnect)
     self.assertEqual(self.consumer._channel, None)
     mock_log.error.assert_called_once_with(repr(error_message))
Example #2
0
 def _adapter_connect(self):
     """Connect to the RabbitMQ broker"""
     super(BlockingConnection, self)._adapter_connect()
     LOGGER.debug('Post initial config, setting to blocking behaviors')
     self.socket.setblocking(1)
     self.socket.settimeout(self.params.socket_timeout)
     self._socket_timeouts = 0
     self._on_connected()
     self._timeouts = dict()
     self._wait_on_open()
     if not self.is_open:
         raise exceptions.AMQPConnectionError(self.SOCKET_TIMEOUT_THRESHOLD)
     LOGGER.debug('Adapter connected')
Example #3
0
    def _wait_on_open(self):
        """When using a high availability cluster (such as HAProxy) we are
        always able to connect even though there might be no RabbitMQ backend.
        So loop while trying to open for up to self.SOCKET_TIMEOUT_THRESHOLD

        """
        socket_timeout_retries = 0
        while (not self.is_open
               and socket_timeout_retries < self.SOCKET_TIMEOUT_THRESHOLD):
            self._flush_outbound()
            try:
                self._handle_read()
            except socket.timeout:
                socket_timeout_retries += 1
            except socket.error, error:
                raise exceptions.AMQPConnectionError(error)
Example #4
0
 def test_publish_reconnect_failed(self):
     # The publisher must try to re-establish a connection on publish, and
     # close the connection if it can't be established.
     self.publisher._channel.publish.side_effect = \
         pika_errs.ConnectionClosed(200, 'I wanted to')
     connection_class_mock = mock.Mock()
     connection_mock = mock.Mock()
     connection_class_mock.return_value = connection_mock
     connection_mock.channel.side_effect = pika_errs.AMQPConnectionError()
     with mock.patch("fedora_messaging._session.pika.BlockingConnection",
                     connection_class_mock):
         self.assertRaises(ConnectionException, self.publisher.publish,
                           self.message)
     # Check that the connection was reestablished
     connection_class_mock.assert_called_with(self.publisher._parameters)
     self.assertEqual(self.publisher._connection, connection_mock)
     connection_mock.close.assert_called_once()
Example #5
0
 def test_publish_disconnected(self):
     # The publisher must try to re-establish a connection on publish.
     self.publisher_channel_publish.side_effect = pika_errs.AMQPConnectionError(
         200, "I wanted to"
     )
     connection_class_mock = mock.Mock()
     connection_mock = mock.Mock()
     channel_mock = mock.Mock()
     connection_class_mock.return_value = connection_mock
     connection_mock.channel.return_value = channel_mock
     with mock.patch(
         "fedora_messaging._session.pika.BlockingConnection", connection_class_mock
     ):
         self.publisher.publish(self.message)
     # Check that the connection was reestablished
     connection_class_mock.assert_called_with(self.publisher._parameters)
     channel_mock.confirm_delivery.assert_called_once()
     self.assertEqual(self.publisher._connection, connection_mock)
     self.assertEqual(self.publisher._channel, channel_mock)
     publish_mock_method = channel_mock.basic_publish
     publish_mock_method.assert_called_once()
Example #6
0
    def _adapter_connect(self):
        """Connect to the RabbitMQ broker

        :rtype: bool
        :raises: pika.Exceptions.AMQPConnectionError

        """
        # Remove the default behavior for connection errors
        self.callbacks.remove(0, self.ON_CONNECTION_ERROR)
        error = super(BlockingConnection, self)._adapter_connect()
        if error:
            raise exceptions.AMQPConnectionError(error)
        self.socket.settimeout(self.SOCKET_CONNECT_TIMEOUT)
        self._frames_written_without_read = 0
        self._socket_timeouts = 0
        self._timeouts = dict()
        self._read_poller = ReadPoller(self.socket.fileno())
        self._on_connected()
        while not self.is_open:
            self.process_data_events()
        self.socket.settimeout(self.params.socket_timeout)
        self._set_connection_state(self.CONNECTION_OPEN)
Example #7
0
 def connectionFailed(self, connection_unused):
     d, self.ready = self.ready, None
     if d:
         attempts = self.params.connection_attempts
         exc = exceptions.AMQPConnectionError(attempts)
         d.errback(exc)
Example #8
0
class BaseConnection(connection.Connection):
    """BaseConnection class that should be extended by connection adapters"""

    # Use epoll's constants to keep life easy
    READ = 0x0001
    WRITE = 0x0004
    ERROR = 0x0008

    ERRORS_TO_IGNORE = [errno.EWOULDBLOCK, errno.EAGAIN, errno.EINTR]
    DO_HANDSHAKE = True
    WARN_ABOUT_IOLOOP = False

    def __init__(self,
                 parameters=None,
                 on_open_callback=None,
                 stop_ioloop_on_close=True):
        """Create a new instance of the Connection object.

        :param pika.connection.Parameters parameters: Connection parameters
        :param method on_open_callback: Method to call on connection open
        :param bool stop_ioloop_on_close: Will stop the ioloop when the
                connection is fully closed.
        :raises: RuntimeError

        """
        # Let the developer know we could not import SSL
        if parameters and parameters.ssl and not ssl:
            raise RuntimeError("SSL specified but it is not available")
        self.fd = None
        self.ioloop = None
        self.stop_ioloop_on_close = stop_ioloop_on_close
        self.base_events = self.READ | self.ERROR
        self.event_state = self.base_events
        self.socket = None
        self.write_buffer = None
        super(BaseConnection, self).__init__(parameters, on_open_callback)

    def add_timeout(self, deadline, callback_method):
        """Add the callback_method to the IOLoop timer to fire after deadline
        seconds. Returns a handle to the timeout

        :param int deadline: The number of seconds to wait to call callback
        :param method callback_method: The callback method
        :rtype: str

        """
        return self.ioloop.add_timeout(deadline, callback_method)

    def close(self, reply_code=200, reply_text='Normal shutdown'):
        """Disconnect from RabbitMQ. If there are any open channels, it will
        attempt to close them prior to fully disconnecting. Channels which
        have active consumers will attempt to send a Basic.Cancel to RabbitMQ
        to cleanly stop the delivery of messages prior to closing the channel.

        :param int reply_code: The code number for the close
        :param str reply_text: The text reason for the close

        """
        super(BaseConnection, self).close(reply_code, reply_text)
        self._handle_ioloop_stop()

    def remove_timeout(self, timeout_id):
        """Remove the timeout from the IOLoop by the ID returned from
        add_timeout.

        :rtype: str

        """
        self.ioloop.remove_timeout(timeout_id)

    def _adapter_connect(self):
        """Connect to the RabbitMQ broker"""
        LOGGER.debug('Connecting the adapter to the remote host')
        reason = 'Unknown'
        remaining_attempts = self.params.connection_attempts
        while remaining_attempts:
            remaining_attempts -= 1
            try:
                self._create_and_connect_to_socket()
                return
            except socket.timeout:
                reason = 'timeout'
            except socket.error, err:
                LOGGER.error('socket error: %s', err[-1])
                reason = err[-1]
                self.socket.close()

            LOGGER.warning('Could not connect due to "%s," retrying in %i sec',
                           reason, self.params.retry_delay)
            if remaining_attempts:
                time.sleep(self.params.retry_delay)

        LOGGER.error('Could not connect: %s', reason)
        raise exceptions.AMQPConnectionError(self.params.connection_attempts *
                                             self.params.retry_delay)
Example #9
0
 def test_amqp_connection_error_two_params_repr(self):
     self.assertEqual(repr(exceptions.AMQPConnectionError(1, 'Test')),
                      'AMQPConnectionError: (1) Test')
Example #10
0
 def test_amqp_connection_error_one_param_repr(self):
     self.assertEqual(repr(exceptions.AMQPConnectionError(10)),
                      'AMQPConnectionError: (10,)')
Example #11
0
 def test_amqp_connection_error_one_param_repr(self):
     self.assertEqual(
         repr(exceptions.AMQPConnectionError(10)),
         "No connection could be opened after 10 connection attempts")
Example #12
0
 def on_open_error(conn, err):
     create_connection_future.set_exception(
         pika_exceptions.AMQPConnectionError(err))
Example #13
0
 def _on_connection_failed(self, _connection, _error_message=None):
     d, self.ready = self.ready, None
     if d:
         attempts = self._impl.params.connection_attempts
         exc = exceptions.AMQPConnectionError(attempts)
         d.errback(exc)
Example #14
0
 def connection_failed(self, connection_unused, error_message=None):
     d, self.ready = self.ready, None
     if d:
         attempts = self.params.connection_attempts
         exc = exceptions.AMQPConnectionError(attempts)
         d.set_exception(exc)
Example #15
0
 def on_open_connection_error(self, unused_connection, error_message=None):
     err('[XMQP] on_open_connection_error %s' % repr(pika_exceptions.AMQPConnectionError(error_message or
         self._connection.params.connection_attempts)))
     self._connection.ioloop.stop()
Example #16
0
                self._socket_connect()
                return
            except socket.timeout, timeout:
                reason = "timeout"
            except socket.error, err:
                reason = err[-1]
                self.socket.close()
            retry = ''
            if remaining_attempts:
                retry = "Retrying in %i seconds with %i retry(s) left" %\
                        (self.params.retry_delay, remaining_attempts)
            LOGGER.warning("Could not connect: %s. %s", reason, retry)
            if remaining_attempts:
                time.sleep(self.params.retry_delay)
        LOGGER.error("Could not connect: %s", reason)
        raise exceptions.AMQPConnectionError(reason)

    def _adapter_disconnect(self):
        """Invoked if the connection is being told to disconnect"""
        self.socket.shutdown(socket.SHUT_RDWR)
        self._check_state_on_disconnect()
        self._handle_ioloop_stop()

    def _check_state_on_disconnect(self):
        """
        Checks to see if we were in opening a connection with RabbitMQ when
        we were disconnected and raises exceptions for the anticipated
        exception types.
        """
        if self.connection_state == self.CONNECTION_PROTOCOL:
            LOGGER.error("Incompatible Protocol Versions")