예제 #1
0
    def test_heartbeat_register_writes(self):
        heartbeat = Heartbeat(60, fake_function)
        time.sleep(0.01)
        for _ in range(32):
            heartbeat.register_write()

        self.assertEqual(heartbeat._writes_since_check, 32)
예제 #2
0
 def __init__(self, hostname, username, password, port=5672, **kwargs):
     """
     :param str hostname: Hostname
     :param str username: Username
     :param str password: Password
     :param int port: Server port
     :param str virtual_host: Virtualhost
     :param int heartbeat: RabbitMQ Heartbeat interval
     :param int|float timeout: Socket timeout
     :param bool ssl: Enable SSL
     :param dict ssl_options: SSL kwargs (from ssl.wrap_socket)
     :param bool lazy: Lazy initialize the connection
     :return:
     """
     super(Connection, self).__init__()
     self.parameters = {
         'hostname': hostname,
         'username': username,
         'password': password,
         'port': port,
         'virtual_host': kwargs.get('virtual_host', '/'),
         'heartbeat': kwargs.get('heartbeat', 60),
         'timeout': kwargs.get('timeout', 30),
         'ssl': kwargs.get('ssl', False),
         'ssl_options': kwargs.get('ssl_options', {})
     }
     self._validate_parameters()
     self.heartbeat = Heartbeat(self.parameters['heartbeat'])
     self._io = IO(self.parameters, on_read=self._read_buffer)
     self._channel0 = Channel0(self)
     self._channels = {}
     if not kwargs.get('lazy', False):
         self.open()
예제 #3
0
    def test_heartbeat_register_reads(self):
        heartbeat = Heartbeat(60, fake_function)
        time.sleep(0.01)
        for _ in range(100):
            heartbeat.register_read()

        self.assertEqual(heartbeat._reads_since_check, 100)
예제 #4
0
    def test_heartbeat_register_writes(self):
        heartbeat = Heartbeat(60, fake_function)
        time.sleep(0.01)
        for _ in range(32):
            heartbeat.register_write()

        self.assertEqual(heartbeat._writes_since_check, 32)
예제 #5
0
 def __init__(self, hostname, username, password, port=5672, **kwargs):
     super(Connection, self).__init__()
     self.parameters = {
         'hostname': hostname,
         'username': username,
         'password': password,
         'port': port,
         'virtual_host': kwargs.get('virtual_host', DEFAULT_VIRTUAL_HOST),
         'heartbeat': kwargs.get('heartbeat', DEFAULT_HEARTBEAT_INTERVAL),
         'timeout': kwargs.get('timeout', DEFAULT_SOCKET_TIMEOUT),
         'ssl': kwargs.get('ssl', False),
         'ssl_options': kwargs.get('ssl_options', {}),
         'client_properties': kwargs.get('client_properties', {})
     }
     self._validate_parameters()
     self._io = IO(self.parameters,
                   exceptions=self._exceptions,
                   on_read_impl=self._read_buffer)
     self._channel0 = Channel0(self, self.parameters['client_properties'])
     self._channels = {}
     self._last_channel_id = None
     self.heartbeat = Heartbeat(self.parameters['heartbeat'],
                                self._channel0.send_heartbeat)
     if not kwargs.get('lazy', False):
         self.open()
예제 #6
0
    def test_heartbeat_do_not_start_new_timer_when_stopped(self):
        heartbeat = Heartbeat(60, fake_function)

        self.assertIsNone(heartbeat._timer)

        heartbeat._start_new_timer()

        self.assertIsNone(heartbeat._timer)
예제 #7
0
    def test_heartbeat_do_not_start_new_timer_when_stopped(self):
        heartbeat = Heartbeat(60, fake_function)

        self.assertIsNone(heartbeat._timer)

        heartbeat._start_new_timer()

        self.assertIsNone(heartbeat._timer)
예제 #8
0
    def test_heartbeat_raise_when_check_for_life_when_exceptions_not_set(self):
        heartbeat = Heartbeat(1)
        heartbeat._beats_since_check = 0
        heartbeat._last_heartbeat = time.time() - 100

        # Normally the exception should be passed down to the list of
        # exceptions in the connection, but if that list for some obscure
        # reason is None, we should raise directly in _check_for_life_signs.
        self.assertRaises(AMQPConnectionError, heartbeat._check_for_life_signs)
예제 #9
0
    def test_heartbeat_disabled(self):
        heartbeat = Heartbeat(0, fake_function)

        self.assertFalse(heartbeat._running.is_set())

        heartbeat.start([])

        self.assertFalse(heartbeat._running.is_set())
        self.assertIsNone(heartbeat._timer)
예제 #10
0
    def test_heartbeat_disabled(self):
        heartbeat = Heartbeat(0, fake_function)

        self.assertFalse(heartbeat._running.is_set())

        heartbeat.start([])

        self.assertFalse(heartbeat._running.is_set())
        self.assertIsNone(heartbeat._timer)
예제 #11
0
    def test_heartbeat_interval(self):
        heartbeat = Heartbeat(60, fake_function)

        self.assertEqual(heartbeat._interval, 60)
        self.assertEqual(heartbeat._threshold, 0)

        heartbeat = Heartbeat(360, fake_function)

        self.assertEqual(heartbeat._interval, 360)
        self.assertEqual(heartbeat._threshold, 0)
예제 #12
0
    def test_heartbeat_basic_raise_on_missed_heartbeats(self):
        heartbeat = Heartbeat(0.01, fake_function)
        exceptions = []

        self.assertTrue(heartbeat.start(exceptions))

        time.sleep(0.1)

        self.assertGreater(len(heartbeat._exceptions), 0)

        heartbeat.stop()
예제 #13
0
    def test_heartbeat_basic_raise_on_missed_heartbeats(self):
        heartbeat = Heartbeat(0.01, fake_function)
        exceptions = []

        self.assertTrue(heartbeat.start(exceptions))

        time.sleep(0.1)

        self.assertGreater(len(heartbeat._exceptions), 0)

        heartbeat.stop()
예제 #14
0
    def test_heartbeat_raise_when_check_for_life_when_exceptions_not_set(self):
        heartbeat = Heartbeat(60, fake_function)
        heartbeat._running.set()
        heartbeat._reads_since_check = 0
        heartbeat._threshold = 3
        heartbeat.register_write()

        # Normally the exception should be passed down to the list of
        # exceptions in the connection, but if that list for some obscure
        # reason is None, we should raise directly in _check_for_life_signs.
        self.assertRaises(AMQPConnectionError, heartbeat._check_for_life_signs)
예제 #15
0
    def test_heartbeat_start(self):
        heartbeat = Heartbeat(60, fake_function)

        self.assertFalse(heartbeat._running.is_set())

        heartbeat.start([])

        self.assertTrue(heartbeat._running.is_set())

        self.assertIsNotNone(heartbeat._timer)
        heartbeat.stop()
예제 #16
0
    def test_heartbeat_no_interval(self):
        heartbeat = Heartbeat(0, fake_function)

        self.assertEqual(heartbeat._interval, 0)
        self.assertEqual(heartbeat._threshold, 0)
        self.assertFalse(heartbeat.start([]))

        heartbeat = Heartbeat(None, fake_function)

        self.assertEqual(heartbeat._interval, None)
        self.assertEqual(heartbeat._threshold, 0)
        self.assertFalse(heartbeat.start([]))
예제 #17
0
    def test_heartbeat_threshold_reset(self):
        heartbeat = Heartbeat(60, fake_function)
        heartbeat._running.set()
        heartbeat.register_write()

        self.assertEqual(heartbeat._threshold, 0)
        self.assertTrue(heartbeat._check_for_life_signs())
        self.assertEqual(heartbeat._threshold, 1)

        heartbeat.register_write()
        heartbeat.register_read()

        self.assertTrue(heartbeat._check_for_life_signs())
        self.assertEqual(heartbeat._threshold, 0)
예제 #18
0
    def test_heartbeat_raise_after_threshold(self):
        heartbeat = Heartbeat(60, fake_function)
        exceptions = []

        self.assertTrue(heartbeat.start(exceptions))

        heartbeat.register_write()

        self.assertTrue(heartbeat._check_for_life_signs())

        heartbeat.register_write()

        self.assertFalse(heartbeat._check_for_life_signs())
        self.assertTrue(exceptions)

        heartbeat.stop()
예제 #19
0
 def __init__(self, hostname, username, password, port=5672, **kwargs):
     """
     :param str hostname: Hostname
     :param str username: Username
     :param str password: Password
     :param int port: Server port
     :param str virtual_host: Virtualhost
     :param int heartbeat: RabbitMQ Heartbeat interval
     :param int|float timeout: Socket timeout
     :param bool ssl: Enable SSL
     :param dict ssl_options: SSL kwargs (from ssl.wrap_socket)
     :param bool lazy: Lazy initialize the connection
     :return:
     """
     super(Connection, self).__init__()
     self.parameters = {
         'hostname': hostname,
         'username': username,
         'password': password,
         'port': port,
         'virtual_host': kwargs.get('virtual_host', '/'),
         'heartbeat': kwargs.get('heartbeat', 60),
         'timeout': kwargs.get('timeout', 30),
         'ssl': kwargs.get('ssl', False),
         'ssl_options': kwargs.get('ssl_options', {})
     }
     self._validate_parameters()
     self.heartbeat = Heartbeat(self.parameters['heartbeat'])
     self._io = IO(self.parameters, on_read=self._read_buffer)
     self._channel0 = Channel0(self)
     self._channels = {}
     if not kwargs.get('lazy', False):
         self.open()
예제 #20
0
    def test_heartbeat_raise_exception(self):
        heartbeat = Heartbeat(60, None)

        self.assertRaisesRegexp(
            AMQPConnectionError,
            'Connection dead, no heartbeat or data received in >= 120s',
            heartbeat._raise_or_append_exception
        )

        heartbeat = Heartbeat(120, None)

        self.assertRaisesRegexp(
            AMQPConnectionError,
            'Connection dead, no heartbeat or data received in >= 240',
            heartbeat._raise_or_append_exception
        )
예제 #21
0
    def test_heartbeat_threshold_reset(self):
        heartbeat = Heartbeat(60, fake_function)
        heartbeat._running.set()
        heartbeat.register_write()

        self.assertEqual(heartbeat._threshold, 0)
        self.assertTrue(heartbeat._check_for_life_signs())
        self.assertEqual(heartbeat._threshold, 1)

        heartbeat.register_write()
        heartbeat.register_read()

        self.assertTrue(heartbeat._check_for_life_signs())
        self.assertEqual(heartbeat._threshold, 0)
예제 #22
0
    def __init__(self, hostname, username, password, port=5672, **kwargs):
        """
        :param str hostname: Hostname
        :param str username: Username
        :param str password: Password
        :param int port: Server port
        :param str virtual_host: Virtual host
        :param int heartbeat: RabbitMQ Heartbeat interval
        :param int|float timeout: Socket timeout
        :param bool ssl: Enable SSL
        :param dict ssl_options: SSL kwargs (from ssl.wrap_socket)
        :param dict client_properties: None or dict of client properties
        :param bool lazy: Lazy initialize the connection

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.

        :return:
        """
        super(Connection, self).__init__()
        self.parameters = {
            'hostname': hostname,
            'username': username,
            'password': password,
            'port': port,
            'virtual_host': kwargs.get('virtual_host', DEFAULT_VIRTUAL_HOST),
            'heartbeat': kwargs.get('heartbeat', DEFAULT_HEARTBEAT_INTERVAL),
            'timeout': kwargs.get('timeout', DEFAULT_SOCKET_TIMEOUT),
            'ssl': kwargs.get('ssl', False),
            'ssl_options': kwargs.get('ssl_options', {}),
            'client_properties': kwargs.get('client_properties', {})
        }
        self._validate_parameters()
        self._io = IO(self.parameters,
                      exceptions=self._exceptions,
                      on_read_impl=self._read_buffer)
        self._channel0 = Channel0(self, self.parameters['client_properties'])
        self._channels = {}
        self._last_channel_id = None
        self.heartbeat = Heartbeat(self.parameters['heartbeat'],
                                   self._channel0.send_heartbeat)
        if not kwargs.get('lazy', False):
            self.open()
예제 #23
0
 def test_heartbeat_register_heartbeat(self):
     heartbeat = Heartbeat(1)
     heartbeat.start([])
     last_heartbeat = heartbeat._last_heartbeat
     time.sleep(0.01)
     heartbeat.register_heartbeat()
     self.assertNotEqual(heartbeat._last_heartbeat, last_heartbeat)
예제 #24
0
    def test_heartbeat_append_exception(self):
        heartbeat = Heartbeat(60, None)
        heartbeat._exceptions = []

        def check(exception):
            heartbeat._raise_or_append_exception()
            if exception:
                raise exception.pop()

        self.assertRaisesRegexp(
            AMQPConnectionError,
            'Connection dead, no heartbeat or data received in >= 120s',
            check, heartbeat._exceptions
        )

        heartbeat._interval = 120

        self.assertRaisesRegexp(
            AMQPConnectionError,
            'Connection dead, no heartbeat or data received in >= 240',
            check, heartbeat._exceptions
        )
예제 #25
0
    def test_heartbeat_append_exception(self):
        heartbeat = Heartbeat(60, None)
        heartbeat._exceptions = []

        def check(exception):
            heartbeat._raise_or_append_exception()
            if exception:
                raise exception.pop()

        self.assertRaisesRegexp(
            AMQPConnectionError,
            'Connection dead, no heartbeat or data received in >= 120s',
            check, heartbeat._exceptions
        )

        heartbeat._interval = 120

        self.assertRaisesRegexp(
            AMQPConnectionError,
            'Connection dead, no heartbeat or data received in >= 240',
            check, heartbeat._exceptions
        )
예제 #26
0
    def test_heartbeat_raise_when_check_for_life_when_exceptions_not_set(self):
        heartbeat = Heartbeat(60, fake_function)
        heartbeat._running.set()
        heartbeat._reads_since_check = 0
        heartbeat._threshold = 3
        heartbeat.register_write()

        # Normally the exception should be passed down to the list of
        # exceptions in the connection, but if that list for some obscure
        # reason is None, we should raise directly in _check_for_life_signs.
        self.assertRaises(AMQPConnectionError, heartbeat._check_for_life_signs)
예제 #27
0
    def test_heartbeat_start(self):
        heartbeat = Heartbeat(60, fake_function)

        self.assertFalse(heartbeat._running.is_set())

        heartbeat.start([])

        self.assertTrue(heartbeat._running.is_set())

        self.assertIsNotNone(heartbeat._timer)
        heartbeat.stop()
예제 #28
0
    def test_heartbeat_send_heartbeat(self):
        self.beats = 0

        def send_heartbeat():
            self.beats += 1

        heartbeat = Heartbeat(60, send_heartbeat=send_heartbeat)
        heartbeat._running.set()

        for _ in range(10):
            heartbeat.register_read()
            self.assertTrue(heartbeat._check_for_life_signs())
        self.assertEqual(self.beats, 10)

        heartbeat.stop()
예제 #29
0
    def test_heartbeat_no_interval(self):
        heartbeat = Heartbeat(0, fake_function)

        self.assertEqual(heartbeat._interval, 0)
        self.assertEqual(heartbeat._threshold, 0)
        self.assertFalse(heartbeat.start([]))

        heartbeat = Heartbeat(None, fake_function)

        self.assertEqual(heartbeat._interval, None)
        self.assertEqual(heartbeat._threshold, 0)
        self.assertFalse(heartbeat.start([]))
예제 #30
0
    def __init__(self, hostname, username, password, port=5672, **kwargs):
        """
        :param str hostname: Hostname
        :param str username: Username
        :param str password: Password
        :param int port: Server port
        :param str virtual_host: Virtual host
        :param int heartbeat: RabbitMQ Heartbeat interval
        :param int|float timeout: Socket timeout
        :param bool ssl: Enable SSL
        :param dict ssl_options: SSL kwargs (from ssl.wrap_socket)
        :param bool lazy: Lazy initialize the connection

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.

        :return:
        """
        super(Connection, self).__init__()
        self.parameters = {
            'hostname': hostname,
            'username': username,
            'password': password,
            'port': port,
            'virtual_host': kwargs.get('virtual_host', DEFAULT_VIRTUAL_HOST),
            'heartbeat': kwargs.get('heartbeat', DEFAULT_HEARTBEAT_INTERVAL),
            'timeout': kwargs.get('timeout', DEFAULT_SOCKET_TIMEOUT),
            'ssl': kwargs.get('ssl', False),
            'ssl_options': kwargs.get('ssl_options', {})
        }
        self._validate_parameters()
        self._io = IO(self.parameters, exceptions=self._exceptions,
                      on_read_impl=self._read_buffer)
        self._channel0 = Channel0(self)
        self._channels = {}
        self._last_channel_id = None
        self.heartbeat = Heartbeat(self.parameters['heartbeat'],
                                   self._channel0.send_heartbeat)
        if not kwargs.get('lazy', False):
            self.open()
예제 #31
0
    def test_heartbeat_send_heartbeat(self):
        self.beats = 0

        def send_heartbeat():
            self.beats += 1

        heartbeat = Heartbeat(60, send_heartbeat_impl=send_heartbeat)
        heartbeat._running.set()

        for _ in range(8):
            heartbeat.register_read()
            self.assertTrue(heartbeat._check_for_life_signs())

        self.assertEqual(self.beats, 8)

        heartbeat.stop()
예제 #32
0
    def test_heartbeat_minimum_interval(self):
        heartbeat = Heartbeat(0.1)

        self.assertEqual(heartbeat._interval, 2)
        self.assertEqual(heartbeat._threshold, 4)
예제 #33
0
    def test_heartbeat_do_not_execute_life_signs_when_stopped(self):
        heartbeat = Heartbeat(60, fake_function)

        self.assertFalse(heartbeat._check_for_life_signs())
예제 #34
0
    def test_heartbeat_running_cleared_after_raise(self):
        heartbeat = Heartbeat(60, fake_function)
        exceptions = []

        self.assertTrue(heartbeat.start(exceptions))
        self.assertTrue(heartbeat._running.is_set())

        heartbeat.register_write()
        heartbeat._check_for_life_signs()
        heartbeat.register_write()
        heartbeat._check_for_life_signs()

        self.assertFalse(heartbeat._running.is_set())

        heartbeat.stop()
예제 #35
0
    def test_heartbeat_extended_loop(self):
        self.beats = 0

        def send_heartbeat():
            self.beats += 1

        heartbeat = Heartbeat(60, send_heartbeat_impl=send_heartbeat)
        heartbeat._running.set()
        heartbeat.register_read()

        # Miss one write/
        self.assertTrue(heartbeat._check_for_life_signs())

        for _ in range(32):
            heartbeat.register_read()
            heartbeat.register_write()

            self.assertFalse(heartbeat._threshold)
            self.assertTrue(heartbeat._check_for_life_signs())

            time.sleep(0.01)

        heartbeat.register_write()

        # Miss one read.
        self.assertTrue(heartbeat._check_for_life_signs())

        self.assertEqual(heartbeat._threshold, 1)
        self.assertEqual(self.beats, 1)

        heartbeat.register_read()
        heartbeat.register_write()
        self.assertTrue(heartbeat._check_for_life_signs())

        self.assertEqual(heartbeat._threshold, 0)

        heartbeat.stop()
예제 #36
0
    def test_heartbeat_extended_loop(self):
        self.beats = 0

        def send_heartbeat():
            self.beats += 1

        heartbeat = Heartbeat(60, send_heartbeat=send_heartbeat)
        heartbeat._running.set()
        heartbeat.register_read()

        # Miss one write/
        self.assertTrue(heartbeat._check_for_life_signs())

        for _ in range(32):
            heartbeat.register_read()
            heartbeat.register_write()

            self.assertFalse(heartbeat._threshold)
            self.assertTrue(heartbeat._check_for_life_signs())

            time.sleep(0.01)

        heartbeat.register_write()

        # Miss one read.
        self.assertTrue(heartbeat._check_for_life_signs())

        self.assertEqual(heartbeat._threshold, 1)
        self.assertEqual(self.beats, 1)

        heartbeat.register_read()
        heartbeat.register_write()
        self.assertTrue(heartbeat._check_for_life_signs())

        self.assertEqual(heartbeat._threshold, 0)

        heartbeat.stop()
예제 #37
0
class Connection(Stateful):
    """RabbitMQ Connection."""
    __slots__ = ['heartbeat', 'parameters', '_channel0', '_channels', '_io']

    def __init__(self, hostname, username, password, port=5672, **kwargs):
        """
        :param str hostname: Hostname
        :param str username: Username
        :param str password: Password
        :param int port: Server port
        :param str virtual_host: Virtual host
        :param int heartbeat: RabbitMQ Heartbeat interval
        :param int|float timeout: Socket timeout
        :param bool ssl: Enable SSL
        :param dict ssl_options: SSL kwargs (from ssl.wrap_socket)
        :param bool lazy: Lazy initialize the connection

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.

        :return:
        """
        super(Connection, self).__init__()
        self.parameters = {
            'hostname': hostname,
            'username': username,
            'password': password,
            'port': port,
            'virtual_host': kwargs.get('virtual_host', '/'),
            'heartbeat': kwargs.get('heartbeat', 60),
            'timeout': kwargs.get('timeout', 10),
            'ssl': kwargs.get('ssl', False),
            'ssl_options': kwargs.get('ssl_options', {})
        }
        self._validate_parameters()
        self._io = IO(self.parameters,
                      exceptions=self._exceptions,
                      on_read=self._read_buffer)
        self._channel0 = Channel0(self)
        self._channels = {}
        self.heartbeat = Heartbeat(self.parameters['heartbeat'],
                                   self._channel0.send_heartbeat)
        if not kwargs.get('lazy', False):
            self.open()

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception_value, _):
        if exception_type:
            message = 'Closing connection due to an unhandled exception: %s'
            LOGGER.warning(message, exception_value)
        self.close()

    @property
    def fileno(self):
        """Returns the Socket File number.

        :return:
        """
        if not self._io.socket:
            return None
        return self._io.socket.fileno()

    @property
    def is_blocked(self):
        """Is the connection currently being blocked from publishing by
        the remote server.

        :rtype: bool
        """
        return self._channel0.is_blocked

    @property
    def server_properties(self):
        """Returns the RabbitMQ Server Properties.

        :rtype: dict
        """
        return self._channel0.server_properties

    @property
    def socket(self):
        """Returns an instance of the Socket used by the Connection.

        :rtype: socket
        """
        return self._io.socket

    def channel(self, rpc_timeout=60):
        """Open Channel.

        :param int rpc_timeout: Timeout before we give up waiting for an RPC
                                response from the server.

        :raises AMQPInvalidArgument: Invalid Parameters
        :raises AMQPChannelError: Raises if the channel encountered an error.
        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        """
        LOGGER.debug('Opening a new Channel')
        if not compatibility.is_integer(rpc_timeout):
            raise AMQPInvalidArgument('rpc_timeout should be an integer')
        elif self.is_closed:
            raise AMQPConnectionError('socket/connection closed')

        with self.lock:
            channel_id = len(self._channels) + 1
            channel = Channel(channel_id, self, rpc_timeout)
            self._channels[channel_id] = channel
            channel.open()
        LOGGER.debug('Channel #%d Opened', channel_id)
        return self._channels[channel_id]

    def check_for_errors(self):
        """Check Connection for errors.

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        :return:
        """
        if not self.exceptions:
            if not self.is_closed:
                return
            why = AMQPConnectionError('connection was closed')
            self.exceptions.append(why)
        self.set_state(self.CLOSED)
        self.close()
        raise self.exceptions[0]

    def close(self):
        """Close connection.

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        :return:
        """
        LOGGER.debug('Connection Closing')
        if not self.is_closed:
            self.set_state(self.CLOSING)
        self.heartbeat.stop()
        try:
            self._close_remaining_channels()
            if not self.is_closed and self.socket:
                self._channel0.send_close_connection()
                self._wait_for_connection_state(state=Stateful.CLOSED)
        except AMQPConnectionError:
            pass
        finally:
            self._io.close()
            self.set_state(self.CLOSED)
        LOGGER.debug('Connection Closed')

    def kill(self):
        for channel in self._channels.values():
            channel.remove_consumer_tag()

        try:
            self._io.close()
        except Exception:
            self._io.kill()

    def open(self):
        """Open Connection.

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        """
        LOGGER.debug('Connection Opening')
        self.set_state(self.OPENING)
        self._exceptions = []
        self._channels = {}
        self._io.open()
        self._send_handshake()
        self._wait_for_connection_state(state=Stateful.OPEN)
        self.heartbeat.start(self._exceptions)
        LOGGER.debug('Connection Opened')

    def write_frame(self, channel_id, frame_out):
        """Marshal and write an outgoing pamqp frame to the Socket.

        :param int channel_id: Channel ID.
        :param specification.Frame frame_out: Amqp frame.

        :return:
        """
        frame_data = pamqp_frame.marshal(frame_out, channel_id)
        self.heartbeat.register_write()
        self._io.write_to_socket(frame_data)

    def write_frames(self, channel_id, frames_out):
        """Marshal and write multiple outgoing pamqp frames to the Socket.

        :param int channel_id: Channel ID/
        :param list frames_out: Amqp frames.

        :return:
        """
        data_out = EMPTY_BUFFER
        for single_frame in frames_out:
            data_out += pamqp_frame.marshal(single_frame, channel_id)
        self.heartbeat.register_write()
        self._io.write_to_socket(data_out)

    def _close_remaining_channels(self):
        """Close any open channels.

        :return:
        """
        for channel_id in self._channels:
            if not self._channels[channel_id].is_open:
                continue
            self._channels[channel_id].set_state(Channel.CLOSED)
            self._channels[channel_id].close()

    def _handle_amqp_frame(self, data_in):
        """Unmarshal a single AMQP frame and return the result.

        :param data_in: socket data
        :return: data_in, channel_id, frame
        """
        if not data_in:
            return data_in, None, None
        try:
            byte_count, channel_id, frame_in = pamqp_frame.unmarshal(data_in)
            return data_in[byte_count:], channel_id, frame_in
        except pamqp_exception.UnmarshalingException:
            pass
        except specification.AMQPFrameError as why:
            LOGGER.error('AMQPFrameError: %r', why, exc_info=True)
        except ValueError as why:
            LOGGER.error(why, exc_info=True)
            self.exceptions.append(AMQPConnectionError(why))
        return data_in, None, None

    def _read_buffer(self, data_in):
        """Process the socket buffer, and direct the data to the appropriate
        channel.

        :rtype: bytes
        """
        while data_in:
            data_in, channel_id, frame_in = \
                self._handle_amqp_frame(data_in)

            if frame_in is None:
                break

            self.heartbeat.register_read()
            if channel_id == 0:
                self._channel0.on_frame(frame_in)
            else:
                self._channels[channel_id].on_frame(frame_in)

        return data_in

    def _send_handshake(self):
        """Send a RabbitMQ Handshake.

        :return:
        """
        self._io.write_to_socket(pamqp_header.ProtocolHeader().marshal())

    def _validate_parameters(self):
        """Validate Connection Parameters.

        :return:
        """
        if not compatibility.is_string(self.parameters['hostname']):
            raise AMQPInvalidArgument('hostname should be a string')
        elif not compatibility.is_integer(self.parameters['port']):
            raise AMQPInvalidArgument('port should be an integer')
        elif not compatibility.is_string(self.parameters['username']):
            raise AMQPInvalidArgument('username should be a string')
        elif not compatibility.is_string(self.parameters['password']):
            raise AMQPInvalidArgument('password should be a string')
        elif not compatibility.is_string(self.parameters['virtual_host']):
            raise AMQPInvalidArgument('virtual_host should be a string')
        elif not isinstance(self.parameters['timeout'], (int, float)):
            raise AMQPInvalidArgument('timeout should be an integer or float')
        elif not compatibility.is_integer(self.parameters['heartbeat']):
            raise AMQPInvalidArgument('heartbeat should be an integer')

    def _wait_for_connection_state(self, state=Stateful.OPEN):
        """Wait for a Connection state.

        :param int state: State that we expect

        :raises AMQPConnectionError: Raises if we reach the connection timeout.

        :return:
        """
        start_time = time.time()
        timeout = (self.parameters['timeout'] or 10) * 3
        while self.current_state != state:
            self.check_for_errors()
            if time.time() - start_time > timeout:
                raise AMQPConnectionError('Connection timed out')
            sleep(IDLE_WAIT)
예제 #38
0
    def test_heartbeat_raise_after_threshold(self):
        heartbeat = Heartbeat(60, fake_function)
        exceptions = []
        heartbeat.start(exceptions)
        heartbeat.register_write()

        self.assertTrue(heartbeat._check_for_life_signs())

        heartbeat.register_write()

        self.assertFalse(heartbeat._check_for_life_signs())
        self.assertTrue(exceptions)

        heartbeat.stop()
예제 #39
0
    def test_heartbeat_do_not_execute_life_signs_when_stopped(self):
        heartbeat = Heartbeat(60, fake_function)

        self.assertFalse(heartbeat._check_for_life_signs())
예제 #40
0
    def test_heartbeat_interval(self):
        heartbeat = Heartbeat(60)

        self.assertEqual(heartbeat._interval, 61)
        self.assertEqual(heartbeat._threshold, 122)
예제 #41
0
class Connection(Stateful):
    """RabbitMQ Connection.

    e.g.
    ::

        import amqpstorm
        connection = amqpstorm.Connection('localhost', 'guest', 'guest')

    Using a SSL Context:
    ::

        import ssl
        import amqpstorm
        ssl_options = {
            'context': ssl.create_default_context(cafile='cacert.pem'),
            'server_hostname': 'rmq.eandersson.net',
            'check_hostname': True,        # New 2.8.0, default is False
            'verify_mode': 'required',     # New 2.8.0, default is 'none'
        }
        connection = amqpstorm.Connection(
            'rmq.eandersson.net', 'guest', 'guest', port=5671,
            ssl=True, ssl_options=ssl_options
        )

    :param str hostname: Hostname
    :param str username: Username
    :param str password: Password
    :param int port: Server port
    :param str virtual_host: Virtual host
    :param int heartbeat: RabbitMQ Heartbeat interval
    :param int,float timeout: Socket timeout
    :param bool ssl: Enable SSL
    :param dict ssl_options: SSL kwargs
    :param dict client_properties: None or dict of client properties
    :param bool lazy: Lazy initialize the connection

    :raises AMQPConnectionError: Raises if the connection
                                 encountered an error.
    """
    __slots__ = ['heartbeat', 'parameters', '_channel0', '_channels', '_io']

    def __init__(self, hostname, username, password, port=5672, **kwargs):
        super(Connection, self).__init__()
        self.parameters = {
            'hostname': hostname,
            'username': username,
            'password': password,
            'port': port,
            'virtual_host': kwargs.get('virtual_host', DEFAULT_VIRTUAL_HOST),
            'heartbeat': kwargs.get('heartbeat', DEFAULT_HEARTBEAT_INTERVAL),
            'timeout': kwargs.get('timeout', DEFAULT_SOCKET_TIMEOUT),
            'ssl': kwargs.get('ssl', False),
            'ssl_options': kwargs.get('ssl_options', {}),
            'client_properties': kwargs.get('client_properties', {})
        }
        self._validate_parameters()
        self._io = IO(self.parameters,
                      exceptions=self._exceptions,
                      on_read_impl=self._read_buffer)
        self._channel0 = Channel0(self, self.parameters['client_properties'])
        self._channels = {}
        self._last_channel_id = None
        self.heartbeat = Heartbeat(self.parameters['heartbeat'],
                                   self._channel0.send_heartbeat)
        if not kwargs.get('lazy', False):
            self.open()

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception_value, _):
        if exception_type:
            message = 'Closing connection due to an unhandled exception: %s'
            LOGGER.warning(message, exception_value)
        self.close()

    @property
    def channels(self):
        """Returns a dictionary of the Channels currently available.

        :rtype: dict
        """
        return self._channels

    @property
    def fileno(self):
        """Returns the Socket File number.

        :rtype: integer,None
        """
        if not self._io.socket:
            return None
        return self._io.socket.fileno()

    @property
    def is_blocked(self):
        """Is the connection currently being blocked from publishing by
        the remote server.

        :rtype: bool
        """
        return self._channel0.is_blocked

    @property
    def max_allowed_channels(self):
        """Returns the maximum allowed channels for the connection.

        :rtype: int
        """
        return self._channel0.max_allowed_channels

    @property
    def max_frame_size(self):
        """Returns the maximum allowed frame size for the connection.

        :rtype: int
        """
        return self._channel0.max_frame_size

    @property
    def server_properties(self):
        """Returns the RabbitMQ Server Properties.

        :rtype: dict
        """
        return self._channel0.server_properties

    @property
    def socket(self):
        """Returns an instance of the Socket used by the Connection.

        :rtype: socket.socket
        """
        return self._io.socket

    def channel(self, rpc_timeout=60, lazy=False):
        """Open a Channel.

        :param int rpc_timeout: Timeout before we give up waiting for an RPC
                                response from the server.

        :raises AMQPInvalidArgument: Invalid Parameters
        :raises AMQPChannelError: Raises if the channel encountered an error.
        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.

        :rtype: amqpstorm.Channel
        """
        LOGGER.debug('Opening a new Channel')
        if not compatibility.is_integer(rpc_timeout):
            raise AMQPInvalidArgument('rpc_timeout should be an integer')
        elif self.is_closed:
            raise AMQPConnectionError('socket/connection closed')

        with self.lock:
            channel_id = self._get_next_available_channel_id()
            channel = Channel(channel_id,
                              self,
                              rpc_timeout,
                              on_close_impl=self._cleanup_channel)
            self._channels[channel_id] = channel
            if not lazy:
                channel.open()
        LOGGER.debug('Channel #%d Opened', channel_id)
        return self._channels[channel_id]

    def check_for_errors(self):
        """Check Connection for errors.

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        :return:
        """
        if not self.exceptions:
            if not self.is_closed:
                return
            why = AMQPConnectionError('connection was closed')
            self.exceptions.append(why)
        self.set_state(self.CLOSED)
        self.close()
        raise self.exceptions[0]

    def close(self):
        """Close the Connection.

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        :return:
        """
        LOGGER.debug('Connection Closing')
        if not self.is_closed:
            self.set_state(self.CLOSING)
        self.heartbeat.stop()
        try:
            if not self.is_closed and self.socket:
                self._channel0.send_close_connection()
                self._wait_for_connection_state(state=Stateful.CLOSED)
        except AMQPConnectionError:
            pass
        finally:
            self._close_remaining_channels()
            self._io.close()
            self.set_state(self.CLOSED)
        LOGGER.debug('Connection Closed')

    def open(self):
        """Open Connection.

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        """
        LOGGER.debug('Connection Opening')
        self.set_state(self.OPENING)
        self._exceptions = []
        self._channels = {}
        self._last_channel_id = None
        self._io.open()
        self._send_handshake()
        self._wait_for_connection_state(state=Stateful.OPEN)
        self.heartbeat.start(self._exceptions)
        LOGGER.debug('Connection Opened')

    def write_frame(self, channel_id, frame_out):
        """Marshal and write an outgoing pamqp frame to the Socket.

        :param int channel_id: Channel ID.
        :param specification.Frame frame_out: Amqp frame.

        :return:
        """
        frame_data = pamqp_frame.marshal(frame_out, channel_id)
        self.heartbeat.register_write()
        self._io.write_to_socket(frame_data)

    def write_frames(self, channel_id, frames_out):
        """Marshal and write multiple outgoing pamqp frames to the Socket.

        :param int channel_id: Channel ID/
        :param list frames_out: Amqp frames.

        :return:
        """
        data_out = EMPTY_BUFFER
        for single_frame in frames_out:
            data_out += pamqp_frame.marshal(single_frame, channel_id)
        self.heartbeat.register_write()
        self._io.write_to_socket(data_out)

    def _close_remaining_channels(self):
        """Forcefully close all open channels.

        :return:
        """
        for channel_id in list(self._channels):
            self._channels[channel_id].set_state(Channel.CLOSED)
            self._channels[channel_id].close()
            self._cleanup_channel(channel_id)

    def _get_next_available_channel_id(self):
        """Returns the next available available channel id.

        :raises AMQPConnectionError: Raises if there is no available channel.
        :rtype: int
        """
        for index in compatibility.RANGE(self._last_channel_id or 1,
                                         self.max_allowed_channels + 1):
            if index in self._channels:
                continue
            self._last_channel_id = index
            return index

        if self._last_channel_id:
            self._last_channel_id = None
            return self._get_next_available_channel_id()

        raise AMQPConnectionError('reached the maximum number of channels %d' %
                                  self.max_allowed_channels)

    def _handle_amqp_frame(self, data_in):
        """Unmarshal a single AMQP frame and return the result.

        :param data_in: socket data

        :return: data_in, channel_id, frame
        """
        if not data_in:
            return data_in, None, None
        try:
            byte_count, channel_id, frame_in = pamqp_frame.unmarshal(data_in)
            return data_in[byte_count:], channel_id, frame_in
        except pamqp_exception.UnmarshalingException:
            pass
        except specification.AMQPFrameError as why:
            LOGGER.error('AMQPFrameError: %r', why, exc_info=True)
        except ValueError as why:
            LOGGER.error(why, exc_info=True)
            self.exceptions.append(AMQPConnectionError(why))
        return data_in, None, None

    def _read_buffer(self, data_in):
        """Process the socket buffer, and direct the data to the appropriate
        channel.

        :rtype: bytes
        """
        while data_in:
            data_in, channel_id, frame_in = self._handle_amqp_frame(data_in)

            if frame_in is None:
                break

            self.heartbeat.register_read()
            if channel_id == 0:
                self._channel0.on_frame(frame_in)
            elif channel_id in self._channels:
                self._channels[channel_id].on_frame(frame_in)

        return data_in

    def _cleanup_channel(self, channel_id):
        """Remove the the channel from the list of available channels.

        :param int channel_id: Channel id

        :return:
        """
        with self.lock:
            if channel_id not in self._channels:
                return
            del self._channels[channel_id]

    def _send_handshake(self):
        """Send a RabbitMQ Handshake.

        :return:
        """
        self._io.write_to_socket(pamqp_header.ProtocolHeader().marshal())

    def _validate_parameters(self):
        """Validate Connection Parameters.

        :return:
        """
        if not compatibility.is_string(self.parameters['hostname']):
            raise AMQPInvalidArgument('hostname should be a string')
        elif not compatibility.is_integer(self.parameters['port']):
            raise AMQPInvalidArgument('port should be an integer')
        elif not compatibility.is_string(self.parameters['username']):
            raise AMQPInvalidArgument('username should be a string')
        elif not compatibility.is_string(self.parameters['password']):
            raise AMQPInvalidArgument('password should be a string')
        elif not compatibility.is_string(self.parameters['virtual_host']):
            raise AMQPInvalidArgument('virtual_host should be a string')
        elif not isinstance(self.parameters['timeout'], (int, float)):
            raise AMQPInvalidArgument('timeout should be an integer or float')
        elif not compatibility.is_integer(self.parameters['heartbeat']):
            raise AMQPInvalidArgument('heartbeat should be an integer')

    def _wait_for_connection_state(self, state=Stateful.OPEN, rpc_timeout=30):
        """Wait for a Connection state.

        :param int state: State that we expect

        :raises AMQPConnectionError: Raises if we are unable to establish
                                     a connection to RabbitMQ.

        :return:
        """
        start_time = time.time()
        while self.current_state != state:
            self.check_for_errors()
            if time.time() - start_time > rpc_timeout:
                raise AMQPConnectionError('Connection timed out')
            sleep(IDLE_WAIT)
예제 #42
0
 def test_heartbeat_basic_raise_on_missed_heartbeats(self):
     exceptions = []
     heartbeat = Heartbeat(1)
     heartbeat.start(exceptions)
     time.sleep(6)
     self.assertGreater(len(heartbeat._exceptions), 0)
예제 #43
0
    def test_heartbeat_running_cleared_after_raise(self):
        heartbeat = Heartbeat(60, fake_function)
        exceptions = []

        self.assertTrue(heartbeat.start(exceptions))
        self.assertTrue(heartbeat._running.is_set())

        heartbeat.register_write()
        heartbeat._check_for_life_signs()
        heartbeat.register_write()
        heartbeat._check_for_life_signs()

        self.assertFalse(heartbeat._running.is_set())

        heartbeat.stop()
예제 #44
0
 def test_heartbeat_stop(self):
     heartbeat = Heartbeat(1)
     heartbeat.start([])
     heartbeat.stop()
     self.assertIsNone(heartbeat._timer)
예제 #45
0
    def test_heartbeat_do_not_execute_life_signs_when_stopped(self):
        heartbeat = Heartbeat(60)
        heartbeat._stopped.set()

        self.assertFalse(heartbeat._check_for_life_signs())
예제 #46
0
class Connection(Stateful):
    """RabbitMQ Connection."""
    __slots__ = [
        'heartbeat', 'parameters', '_channel0', '_channels', '_io'
    ]

    def __init__(self, hostname, username, password, port=5672, **kwargs):
        """
        :param str hostname: Hostname
        :param str username: Username
        :param str password: Password
        :param int port: Server port
        :param str virtual_host: Virtual host
        :param int heartbeat: RabbitMQ Heartbeat interval
        :param int|float timeout: Socket timeout
        :param bool ssl: Enable SSL
        :param dict ssl_options: SSL kwargs (from ssl.wrap_socket)
        :param bool lazy: Lazy initialize the connection

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.

        :return:
        """
        super(Connection, self).__init__()
        self.parameters = {
            'hostname': hostname,
            'username': username,
            'password': password,
            'port': port,
            'virtual_host': kwargs.get('virtual_host', '/'),
            'heartbeat': kwargs.get('heartbeat', 60),
            'timeout': kwargs.get('timeout', 10),
            'ssl': kwargs.get('ssl', False),
            'ssl_options': kwargs.get('ssl_options', {})
        }
        self._validate_parameters()
        self._io = IO(self.parameters, exceptions=self._exceptions,
                      on_read=self._read_buffer)
        self._channel0 = Channel0(self)
        self._channels = {}
        self.heartbeat = Heartbeat(self.parameters['heartbeat'],
                                   self._channel0.send_heartbeat)
        if not kwargs.get('lazy', False):
            self.open()

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception_value, _):
        if exception_type:
            message = 'Closing connection due to an unhandled exception: %s'
            LOGGER.warning(message, exception_value)
        self.close()

    @property
    def fileno(self):
        """Returns the Socket File number.

        :return:
        """
        if not self._io.socket:
            return None
        return self._io.socket.fileno()

    @property
    def is_blocked(self):
        """Is the connection currently being blocked from publishing by
        the remote server.

        :rtype: bool
        """
        return self._channel0.is_blocked

    @property
    def server_properties(self):
        """Returns the RabbitMQ Server Properties.

        :rtype: dict
        """
        return self._channel0.server_properties

    @property
    def socket(self):
        """Returns an instance of the Socket used by the Connection.

        :rtype: socket
        """
        return self._io.socket

    def channel(self, rpc_timeout=60):
        """Open Channel.

        :param int rpc_timeout: Timeout before we give up waiting for an RPC
                                response from the server.

        :raises AMQPInvalidArgument: Invalid Parameters
        :raises AMQPChannelError: Raises if the channel encountered an error.
        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        """
        LOGGER.debug('Opening a new Channel')
        if not compatibility.is_integer(rpc_timeout):
            raise AMQPInvalidArgument('rpc_timeout should be an integer')
        elif self.is_closed:
            raise AMQPConnectionError('socket/connection closed')

        with self.lock:
            channel_id = len(self._channels) + 1
            channel = Channel(channel_id, self, rpc_timeout)
            self._channels[channel_id] = channel
            channel.open()
        LOGGER.debug('Channel #%d Opened', channel_id)
        return self._channels[channel_id]

    def check_for_errors(self):
        """Check Connection for errors.

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        :return:
        """
        if not self.exceptions:
            if not self.is_closed:
                return
            why = AMQPConnectionError('connection was closed')
            self.exceptions.append(why)
        self.set_state(self.CLOSED)
        self.close()
        raise self.exceptions[0]

    def close(self):
        """Close connection.

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        :return:
        """
        LOGGER.debug('Connection Closing')
        if not self.is_closed:
            self.set_state(self.CLOSING)
        self.heartbeat.stop()
        try:
            self._close_remaining_channels()
            if not self.is_closed and self.socket:
                self._channel0.send_close_connection()
                self._wait_for_connection_state(state=Stateful.CLOSED)
        except AMQPConnectionError:
            pass
        finally:
            self._io.close()
            self.set_state(self.CLOSED)
        LOGGER.debug('Connection Closed')

    def kill(self):
        for channel in self._channels.items():
            channel.remove_consumer_tag()

        self._io.kill()


    def open(self):
        """Open Connection.

        :raises AMQPConnectionError: Raises if the connection
                                     encountered an error.
        """
        LOGGER.debug('Connection Opening')
        self.set_state(self.OPENING)
        self._exceptions = []
        self._channels = {}
        self._io.open()
        self._send_handshake()
        self._wait_for_connection_state(state=Stateful.OPEN)
        self.heartbeat.start(self._exceptions)
        LOGGER.debug('Connection Opened')

    def write_frame(self, channel_id, frame_out):
        """Marshal and write an outgoing pamqp frame to the Socket.

        :param int channel_id: Channel ID.
        :param pamqp_spec.Frame frame_out: Amqp frame.

        :return:
        """
        frame_data = pamqp_frame.marshal(frame_out, channel_id)
        self.heartbeat.register_write()
        self._io.write_to_socket(frame_data)

    def write_frames(self, channel_id, frames_out):
        """Marshal and write multiple outgoing pamqp frames to the Socket.

        :param int channel_id: Channel ID/
        :param list frames_out: Amqp frames.

        :return:
        """
        data_out = EMPTY_BUFFER
        for single_frame in frames_out:
            data_out += pamqp_frame.marshal(single_frame, channel_id)
        self.heartbeat.register_write()
        self._io.write_to_socket(data_out)

    def _close_remaining_channels(self):
        """Close any open channels.

        :return:
        """
        for channel_id in self._channels:
            if not self._channels[channel_id].is_open:
                continue
            self._channels[channel_id].set_state(Channel.CLOSED)
            self._channels[channel_id].close()

    def _handle_amqp_frame(self, data_in):
        """Unmarshal a single AMQP frame and return the result.

        :param data_in: socket data
        :return: data_in, channel_id, frame
        """
        if not data_in:
            return data_in, None, None
        try:
            byte_count, channel_id, frame_in = pamqp_frame.unmarshal(data_in)
            return data_in[byte_count:], channel_id, frame_in
        except pamqp_exception.UnmarshalingException:
            pass
        except pamqp_spec.AMQPFrameError as why:
            LOGGER.error('AMQPFrameError: %r', why, exc_info=True)
        except ValueError as why:
            LOGGER.error(why, exc_info=True)
            self.exceptions.append(AMQPConnectionError(why))
        return data_in, None, None

    def _read_buffer(self, data_in):
        """Process the socket buffer, and direct the data to the appropriate
        channel.

        :rtype: bytes
        """
        while data_in:
            data_in, channel_id, frame_in = \
                self._handle_amqp_frame(data_in)

            if frame_in is None:
                break

            self.heartbeat.register_read()
            if channel_id == 0:
                self._channel0.on_frame(frame_in)
            else:
                self._channels[channel_id].on_frame(frame_in)

        return data_in

    def _send_handshake(self):
        """Send a RabbitMQ Handshake.

        :return:
        """
        self._io.write_to_socket(pamqp_header.ProtocolHeader().marshal())

    def _validate_parameters(self):
        """Validate Connection Parameters.

        :return:
        """
        if not compatibility.is_string(self.parameters['hostname']):
            raise AMQPInvalidArgument('hostname should be a string')
        elif not compatibility.is_integer(self.parameters['port']):
            raise AMQPInvalidArgument('port should be an integer')
        elif not compatibility.is_string(self.parameters['username']):
            raise AMQPInvalidArgument('username should be a string')
        elif not compatibility.is_string(self.parameters['password']):
            raise AMQPInvalidArgument('password should be a string')
        elif not compatibility.is_string(self.parameters['virtual_host']):
            raise AMQPInvalidArgument('virtual_host should be a string')
        elif not isinstance(self.parameters['timeout'], (int, float)):
            raise AMQPInvalidArgument('timeout should be an integer or float')
        elif not compatibility.is_integer(self.parameters['heartbeat']):
            raise AMQPInvalidArgument('heartbeat should be an integer')

    def _wait_for_connection_state(self, state=Stateful.OPEN):
        """Wait for a Connection state.

        :param int state: State that we expect

        :raises AMQPConnectionError: Raises if we reach the connection timeout.

        :return:
        """
        start_time = time.time()
        timeout = (self.parameters['timeout'] or 10) * 3
        while self.current_state != state:
            self.check_for_errors()
            if time.time() - start_time > timeout:
                raise AMQPConnectionError('Connection timed out')
            sleep(IDLE_WAIT)
예제 #47
0
 def test_heartbeat_register_beat(self):
     heartbeat = Heartbeat(1)
     heartbeat.start([])
     self.assertEqual(heartbeat._beats_since_check, 0)
     heartbeat.register_beat()
     self.assertEqual(heartbeat._beats_since_check, 1)