Ejemplo n.º 1
0
    def test_in_order_messages_are_handled_in_order(self):
        """Test that messages received in order are handled in order."""
        message_handling_order = []

        message_handler = OrderedMessageHandler(
            subscriber=MockSubscriber(),
            subscription=self.mock_subscription,
            message_handlers={
                "test": self._make_order_recording_message_handler(message_handling_order),
                "finish-test": lambda message: "This is the result.",
            },
        )

        with patch(
            "octue.cloud.pub_sub.service.OrderedMessageHandler._pull_message",
            new=MockMessagePuller(
                messages=[
                    {"type": "test", "message_number": 0},
                    {"type": "test", "message_number": 1},
                    {"type": "test", "message_number": 2},
                    {"type": "finish-test", "message_number": 3},
                ]
            ).pull,
        ):
            result = message_handler.handle_messages()

        self.assertEqual(result, "This is the result.")
        self.assertEqual(message_handling_order, [0, 1, 2])
Ejemplo n.º 2
0
    def test_error_raised_if_delivery_acknowledgement_not_received_in_time(self):
        """Test that an error is raised if delivery acknowledgement isn't received before the given acknowledgement
        timeout.
        """
        message_handler = OrderedMessageHandler(subscriber=MockSubscriber(), subscription=self.mock_subscription)

        with patch("tests.cloud.pub_sub.mocks.MockSubscriber.pull", return_value=MockPullResponse()):
            with self.assertRaises(exceptions.QuestionNotDelivered):
                message_handler.handle_messages(delivery_acknowledgement_timeout=0)
Ejemplo n.º 3
0
    def test_unknown_message_type_raises_warning(self):
        """Test that unknown message types result in a warning being logged."""
        message_handler = OrderedMessageHandler(
            subscriber=MockSubscriber(),
            subscription=self.mock_subscription,
            message_handlers={"finish-test": lambda message: message},
        )

        with patch("logging.StreamHandler.emit") as mock_emit:
            message_handler._handle_message({"type": "blah", "message_number": 0})

        self.assertIn("Received a message of unknown type", mock_emit.call_args_list[0][0][0].msg)
Ejemplo n.º 4
0
    def test_timeout(self):
        """Test that a TimeoutError is raised if message handling takes longer than the given timeout."""
        message_handler = OrderedMessageHandler(
            subscriber=MockSubscriber(),
            subscription=self.mock_subscription,
            message_handlers={
                "test": self._make_order_recording_message_handler([]),
                "finish-test": lambda message: message,
            },
        )

        with patch(
            "octue.cloud.pub_sub.service.OrderedMessageHandler._pull_message",
            new=MockMessagePuller(messages=[{"type": "test", "message_number": 0}]).pull,
        ):
            with self.assertRaises(TimeoutError):
                message_handler.handle_messages(timeout=0)
Ejemplo n.º 5
0
    def wait_for_answer(
        self,
        subscription,
        handle_monitor_message=None,
        service_name="REMOTE",
        timeout=60,
        delivery_acknowledgement_timeout=120,
    ):
        """Wait for an answer to a question on the given subscription, deleting the subscription and its topic once
        the answer is received.

        :param octue.cloud.pub_sub.subscription.Subscription subscription: the subscription for the question's answer
        :param callable|None handle_monitor_message: a function to handle monitor messages (e.g. send them to an endpoint for plotting or displaying) - this function should take a single JSON-compatible python primitive as an argument (note that this could be an array or object)
        :param str service_name: a name by which to refer to the child subscribed to (used for labelling its log messages if subscribed to)
        :param float|None timeout: how long in seconds to wait for an answer before raising a `TimeoutError`
        :param float delivery_acknowledgement_timeout: how long in seconds to wait for a delivery acknowledgement before aborting
        :raise TimeoutError: if the timeout is exceeded
        :raise octue.exceptions.QuestionNotDelivered: if a delivery acknowledgement is not received in time
        :return dict: dictionary containing the keys "output_values" and "output_manifest"
        """
        if subscription.is_push_subscription:
            raise octue.exceptions.PushSubscriptionCannotBePulled(
                f"Cannot pull from {subscription.path!r} subscription as it is a push subscription."
            )

        subscriber = pubsub_v1.SubscriberClient(credentials=self.credentials)

        message_handler = OrderedMessageHandler(
            subscriber=subscriber,
            subscription=subscription,
            handle_monitor_message=handle_monitor_message,
            service_name=service_name,
        )

        try:
            return message_handler.handle_messages(
                timeout=timeout,
                delivery_acknowledgement_timeout=delivery_acknowledgement_timeout,
            )
        finally:
            subscription.delete()
            subscriber.close()
Ejemplo n.º 6
0
    def test_delivery_acknowledgement(self):
        """Test that a delivery acknowledgement message is handled correctly."""
        message_handler = OrderedMessageHandler(subscriber=MockSubscriber(), subscription=self.mock_subscription)
        self.assertFalse(message_handler.received_delivery_acknowledgement)

        with patch(
            "octue.cloud.pub_sub.service.OrderedMessageHandler._pull_message",
            new=MockMessagePuller(
                [
                    {
                        "type": "delivery_acknowledgement",
                        "delivery_time": "2021-11-17 17:33:59.717428",
                        "message_number": 0,
                    },
                    {"type": "result", "output_values": None, "output_manifest": None, "message_number": 1},
                ]
            ).pull,
        ):
            result = message_handler.handle_messages()

        self.assertTrue(message_handler.received_delivery_acknowledgement)
        self.assertEqual(result, {"output_values": None, "output_manifest": None})