Ejemplo n.º 1
0
def test_connect_success(monkeypatch):
    # Test if connect reports connection success
    mock_connection(monkeypatch, connection_success=True)

    connection = AsyncConnection(connection_params)
    assert (connection.connect() is True)
    connection.disconnect()
Ejemplo n.º 2
0
def test_publish_failure(monkeypatch):
    # Test publish failure
    mock_connection(monkeypatch, connection_success=True)

    connection = AsyncConnection(connection_params)
    queue = {"name": "name", "key": "key"}
    with pytest.raises(Exception):
        connection.publish(queue, "key", "message")
Ejemplo n.º 3
0
def test_connect_callback_failure(monkeypatch):
    # Test if connect does not call callback on failure
    mock_connection(monkeypatch, connection_success=False)
    global on_connect_called

    connection = AsyncConnection(connection_params)
    assert (not on_connect_called)
    connection.connect(on_connect)
    assert (not on_connect_called)
Ejemplo n.º 4
0
    def test_on_message(self):

        global return_message

        # setup mocks and fixtures
        mocked_handler = mock.Mock(wraps=handler)
        service = fixtures.get_service_fixture(mocked_handler)
        single_service = [v for v in service.values()][0]

        message = {}
        queue = {'name': single_service['queue']}
        key = {'name': single_service['key']}
        connection = AsyncConnection({})

        # setup expectations
        return_message = fixtures.random_string()
        return_queue = single_service['report']

        with mock.patch.object(connection, "publish") as mocked_publish:

            # on_message = messagedriven_service._get_on_message(single_service)
            result = messagedriven_service._on_message(connection, single_service, message)

            # The result should be True
            self.assertTrue(result)

            # The message handler should be called with the message
            mocked_handler.assert_called_with(message)

            # The return message should be published on the return queue
            mocked_publish.assert_called_with(return_queue, return_queue['key'], return_message)
Ejemplo n.º 5
0
def test_publish(monkeypatch):
    # Test publish message
    mock_connection(monkeypatch, connection_success=True)

    connection = AsyncConnection(connection_params)
    connection.connect()
    queue = {"exchange": "exchange", "name": "name", "key": "key"}
    connection.publish(queue, "key", "message")
    assert (published_message == json.dumps("message"))
    connection.disconnect()
Ejemplo n.º 6
0
def test_connect_context_manager(monkeypatch):
    # Test if context manager calls disconnect on exit with statement
    mock_connection(monkeypatch, connection_success=True)

    org_connection = None
    with patch.object(AsyncConnection, 'disconnect') as mocked_disconnect:
        with AsyncConnection(connection_params) as connection:
            org_connection = connection  # save to call the real disconnect afterwards
            pass
        assert (mocked_disconnect.called)
    org_connection.disconnect()  # Call the real disconnect
Ejemplo n.º 7
0
    def _listen(self, queues: list):
        with AsyncConnection(CONNECTION_PARAMS, self.params) as connection:
            # Subscribe to the queues, handle messages in the on_message function (runs in another thread)
            connection.subscribe(queues, self._on_message)

            id = ', '.join([queue for queue in queues])

            # Repeat forever
            while self.keep_running and connection.is_alive():
                time.sleep(self.check_connection)

            print(f"Queue connection for {id} stopped.")
Ejemplo n.º 8
0
def test_connect_callback_success(monkeypatch):
    # Test if connect calls callback on success
    mock_connection(monkeypatch, connection_success=True)
    global on_connect_called

    assert (not on_connect_called)
    connection = AsyncConnection(connection_params)
    connection.connect(on_connect)
    assert (on_connect_called)
    connection.disconnect()
Ejemplo n.º 9
0
    def _heartbeat_loop(self):
        with AsyncConnection(CONNECTION_PARAMS, self.params) as connection:
            heartbeat = Heartbeat(connection, self.name)

            n = 0

            while self.keep_running and connection.is_alive():
                time.sleep(self.check_connection)

                for thread in self.threads:
                    if not thread['thread'].is_alive():
                        print("ERROR: died thread found")
                        # Create new thread
                        thread['thread'] = self._start_thread(thread['queues'])

                n += self.check_connection

                if n >= self.heartbeat_interval and all([t['thread'].is_alive() for t in self.threads]):
                    heartbeat.send()
                    n = 0
Ejemplo n.º 10
0
def test_disconnect():
    # Test if a disconnect can be called without an earlier connect
    connection = AsyncConnection('')
    assert (connection.disconnect() is None)
Ejemplo n.º 11
0
def publish(exchange, key, msg):
    with AsyncConnection(CONNECTION_PARAMS) as connection:
        connection.publish(exchange, key, msg)
Ejemplo n.º 12
0
def test_connect_failure(monkeypatch):
    # Test if connect reports failure to connect
    mock_connection(monkeypatch, connection_success=False)

    connection = AsyncConnection(connection_params)
    assert (connection.connect() is False)
Ejemplo n.º 13
0
def test_subscribe(monkeypatch):
    # Test subscription and message receipt
    mock_connection(monkeypatch, connection_success=True)

    # connection, exchange, queue, key, msg
    def on_message(self, exchange, queue, key, body):
        assert (key == "mykey")
        assert (body == "mybody")

    connection = AsyncConnection(connection_params)
    connection.connect()
    queue = {"exchange": "exchange", "name": "name", "key": "key"}
    connection.subscribe([queue, queue], on_message)
    connection.publish(queue, "key", "mybody")
    assert (consumed_message == "mybody")

    # connection, exchange, queue, key, msg
    def on_message_fail(self, exchange, queue, key, body):
        raise Exception

    connection.subscribe([queue, queue], on_message_fail)
    connection.publish(queue, "key", "mybody")
    assert (consumed_message == "mybody")

    connection.disconnect()
Ejemplo n.º 14
0
def test_connection_constructor():
    # Test if a connection can be initialized
    connection = AsyncConnection(connection_params)
    assert (connection is not None)
    assert (connection._connection_params == connection_params)
Ejemplo n.º 15
0
    def setUp(self) -> None:
        self.connection_params = {'connection': 'params'}
        self.params = {'other': 'params'}

        self.async_connection = AsyncConnection(self.connection_params,
                                                self.params)
Ejemplo n.º 16
0
class TestAsyncConnection(TestCase):
    def setUp(self) -> None:
        self.connection_params = {'connection': 'params'}
        self.params = {'other': 'params'}

        self.async_connection = AsyncConnection(self.connection_params,
                                                self.params)

    def test_init(self):

        self.assertEqual(
            {
                'load_message': True,
                'stream_contents': False,
                'other': 'params',
                'prefetch_count': 1,
            }, self.async_connection._params)
        self.assertEqual(self.connection_params,
                         self.async_connection._connection_params)
        self.assertFalse(self.async_connection._eventloop_failed)

    def test_enter(self):
        self.async_connection.connect = MagicMock()
        self.assertEqual(self.async_connection,
                         self.async_connection.__enter__())
        self.async_connection.connect.assert_called_once()

    def test_exit(self):
        self.async_connection.disconnect = MagicMock()
        self.async_connection.__exit__()
        self.async_connection.disconnect.assert_called_once()

    def test_is_alive(self):
        self.assertTrue(self.async_connection.is_alive())
        self.async_connection._eventloop_failed = True
        self.assertFalse(self.async_connection.is_alive())

    @patch('builtins.print')
    @patch("gobcore.message_broker.async_message_broker.threading.Thread")
    @patch("gobcore.message_broker.async_message_broker.os._exit")
    def test_on_message_redeliver(self, mock_os_exit, mock_thread, mock_print):
        msg = {'some': 'message'}
        message_handler = MagicMock()
        message_handler.side_effect = Exception
        on_message = self.async_connection.on_message('some queue',
                                                      message_handler)
        channel = MagicMock()
        basic_deliver = MagicMock()
        properties = {}

        basic_deliver.redelivered = False
        on_message(channel, basic_deliver, properties, json.dumps(msg))

        thread_target = mock_thread.call_args[1]['target']
        thread_target()

        mock_os_exit.assert_called_with(os.EX_TEMPFAIL)
        print_msg = mock_print.call_args[0][0]

        self.assertEqual(print_msg,
                         'Message handling has failed, terminating program')

        basic_deliver.redelivered = True
        on_message(channel, basic_deliver, properties, json.dumps(msg))

        thread_target = mock_thread.call_args[1]['target']
        thread_target()

        print_msg = mock_print.call_args[0][0]

        self.assertTrue(
            print_msg.startswith('Message handling has failed on second try'))

    @patch('builtins.print')
    @patch("gobcore.message_broker.async_message_broker.threading.Thread")
    def test_on_message_nack(self, mock_thread, mock_print):
        msg = {'some': 'message'}
        message_handler = MagicMock(return_value=False)
        on_message = self.async_connection.on_message('some queue',
                                                      message_handler)
        channel = MagicMock()
        basic_deliver = MagicMock()

        on_message(channel, basic_deliver, {}, json.dumps(msg))

        thread_target = mock_thread.call_args[1]['target']
        thread_target()

        print_msg = mock_print.call_args[0][0]

        self.assertEqual(print_msg,
                         "Message not acknowlegded, discarding message")
Ejemplo n.º 17
0
def publish(queue_name, key, msg):
    with AsyncConnection(CONNECTION_PARAMS) as connection:
        connection.publish(get_queue(queue_name), key, msg)
Ejemplo n.º 18
0
def test_idempotent_disconnect():
    # Test disconnect repeated execution
    connection = AsyncConnection('')
    assert (connection.disconnect() is None)
    assert (connection.disconnect() is None)
Ejemplo n.º 19
0
def messagedriven_service(services, name, params={}):
    """Start a connection with a the message broker and the given definition

    servicedefenition is a dict of dicts:

    ```
    SERVICEDEFINITION = {
        'unique_key': {
            'exchange': 'name_of_the_exchange_to_listen_to',
            'queue': 'name_of_the_queue_to_listen_to',
            'key': 'name_of_the_key_to_listen_to'
            'handler': 'method_to_invoke_on_message',
             # optional report functionality
            'report': {
                'exchange': 'name_of_the_exchange_to_report_to',
                'queue': 'name_of_the_queue_to_report_to',
                'key': 'name_of_the_key_to_report_to'
            }
        }
    }
    ```

    start the service with:

    ```
    from gobcore.message_broker.messagedriven_service import messagedriven_service

    messagedriven_services(SERVICEDEFINITION)

    """
    heartbeat = None

    def on_message(connection, exchange, queue, key, msg):
        """Called on every message receipt

        :param connection: the connection with the message broker
        :param exchange: the message broker exchange
        :param queue: the message broker queue
        :param key: the identification of the message (e.g. fullimport.proposal)
        :param msg: the contents of the message

        :return:
        """
        print(f"{key} accepted from {queue}, start handling")
        service = _get_service(services, exchange, queue, key)

        result = _on_message(connection, service, msg)

        return result

    # Start by initializing the message broker (idempotent)
    _init()

    with AsyncConnection(CONNECTION_PARAMS, params) as connection:
        # Subscribe to the queues, handle messages in the on_message function (runs in another thread)
        queues = []
        for key, service in services.items():

            queues.append({
                "exchange": service['exchange'],
                "name": service['queue'],
                "key": service['key']
            })
            print(f"Listening to messages {service['key']} on queue {service['queue']}")

        heartbeat = Heartbeat(connection, name)

        connection.subscribe(queues, on_message)

        # Repeat forever
        print("Queue connection for servicedefinition started")
        n = 0
        while keep_running and connection.is_alive():
            time.sleep(CHECK_CONNECTION)
            n += CHECK_CONNECTION
            if n >= HEARTBEAT_INTERVAL:
                heartbeat.send()
                n = 0

        print("Queue connection for servicedefinition has stopped")