def test_poll_queue(self, run_policy_mock, storage_mock, _1, _2, _3): host = Host(DEFAULT_EVENT_QUEUE_ID, DEFAULT_EVENT_QUEUE_NAME, DEFAULT_POLICY_STORAGE) host.policies = { 'one': { 'policy': ContainerHostTest.get_mock_policy({ 'name': 'one', 'mode': { 'type': 'container-event', 'events': ['ResourceGroupWrite', 'VnetWrite'] } }) } } q1 = QueueMessage() q1.id = 1 q1.dequeue_count = 0 q1.content = """eyAgCiAgICJzdWJqZWN0IjoiL3N1YnNjcmlwdGlvbnMvZWE5ODk3NGItNWQyYS00ZDk4LWE3 OGEtMzgyZjM3MTVkMDdlL3Jlc291cmNlR3JvdXBzL3Rlc3RfY29udGFpbmVyX21vZGUiLAogICAiZXZlbnRUeXBlIj oiTWljcm9zb2Z0LlJlc291cmNlcy5SZXNvdXJjZVdyaXRlU3VjY2VzcyIsCiAgICJldmVudFRpbWUiOiIyMDE5LTA3 LTE2VDE4OjMwOjQzLjM1OTUyNTVaIiwKICAgImlkIjoiNjE5ZDI2NzQtYjM5Ni00MzU2LTk2MTktNmM1YTUyZmU0ZT g4IiwKICAgImRhdGEiOnsgICAgICAgIAogICAgICAiY29ycmVsYXRpb25JZCI6IjdkZDVhNDc2LWUwNTItNDBlMi05 OWU0LWJiOTg1MmRjMWY4NiIsCiAgICAgICJyZXNvdXJjZVByb3ZpZGVyIjoiTWljcm9zb2Z0LlJlc291cmNlcyIsCi AgICAgICJyZXNvdXJjZVVyaSI6Ii9zdWJzY3JpcHRpb25zL2VhOTg5NzRiLTVkMmEtNGQ5OC1hNzhhLTM4MmYzNzE1 ZDA3ZS9yZXNvdXJjZUdyb3Vwcy90ZXN0X2NvbnRhaW5lcl9tb2RlIiwKICAgICAgIm9wZXJhdGlvbk5hbWUiOiJNaW Nyb3NvZnQuUmVzb3VyY2VzL3N1YnNjcmlwdGlvbnMvcmVzb3VyY2VHcm91cHMvd3JpdGUiLAogICAgICAic3RhdHVz IjoiU3VjY2VlZGVkIiwKICAgfSwKICAgInRvcGljIjoiL3N1YnNjcmlwdGlvbnMvYWE5ODk3NGItNWQyYS00ZDk4LW E3OGEtMzgyZjM3MTVkMDdlIgp9""" q2 = QueueMessage() q2.id = 2 q2.dequeue_count = 0 q2.content = q1.content # Return 2 messages on first call, then none storage_mock.get_queue_messages.side_effect = [[q1, q2], []] host.poll_queue() self.assertEqual(2, run_policy_mock.call_count) run_policy_mock.reset_mock() # Return 5 messages on first call, then 2, then 0 storage_mock.get_queue_messages.side_effect = [[q1, q1, q1, q1, q1], [q1, q2], []] host.poll_queue() self.assertEqual(7, run_policy_mock.call_count) run_policy_mock.reset_mock() # High dequeue count q1.dequeue_count = 100 storage_mock.get_queue_messages.side_effect = [[q1, q2], []] host.poll_queue() self.assertEqual(1, run_policy_mock.call_count)
def test_run_policy_for_event(self, add_job_mock, _0, _1, _2, _3): host = Host(DEFAULT_EVENT_QUEUE_ID, DEFAULT_EVENT_QUEUE_NAME, DEFAULT_POLICY_STORAGE) host.policies = { 'one': { 'policy': ContainerHostTest.get_mock_policy({ 'name': 'one', 'mode': { 'type': 'container-event', 'events': ['ResourceGroupWrite', 'VnetWrite'] } }) } } message = QueueMessage() message.id = 1 message.dequeue_count = 0 message.content = \ """eyAgCiAgICJzdWJqZWN0IjoiL3N1YnNjcmlwdGlvbnMvZWE5ODk3NGItNWQyYS00ZDk4LWE3OGEt MzgyZjM3MTVkMDdlL3Jlc291cmNlR3JvdXBzL3Rlc3RfY29udGFpbmVyX21vZGUiLAogICAiZXZl bnRUeXBlIjoiTWljcm9zb2Z0LlJlc291cmNlcy5SZXNvdXJjZVdyaXRlU3VjY2VzcyIsCiAgICJl dmVudFRpbWUiOiIyMDE5LTA3LTE2VDE4OjMwOjQzLjM1OTUyNTVaIiwKICAgImlkIjoiNjE5ZDI2 NzQtYjM5Ni00MzU2LTk2MTktNmM1YTUyZmU0ZTg4IiwKICAgImRhdGEiOnsgICAgICAgIAogICAg ICAiY29ycmVsYXRpb25JZCI6IjdkZDVhNDc2LWUwNTItNDBlMi05OWU0LWJiOTg1MmRjMWY4NiIs CiAgICAgICJyZXNvdXJjZVByb3ZpZGVyIjoiTWljcm9zb2Z0LlJlc291cmNlcyIsCiAgICAgICJy ZXNvdXJjZVVyaSI6Ii9zdWJzY3JpcHRpb25zL2VhOTg5NzRiLTVkMmEtNGQ5OC1hNzhhLTM4MmYz NzE1ZDA3ZS9yZXNvdXJjZUdyb3Vwcy90ZXN0X2NvbnRhaW5lcl9tb2RlIiwKICAgICAgIm9wZXJh dGlvbk5hbWUiOiJNaWNyb3NvZnQuUmVzb3VyY2VzL3N1YnNjcmlwdGlvbnMvcmVzb3VyY2VHcm91 cHMvd3JpdGUiLAogICAgICAic3RhdHVzIjoiU3VjY2VlZGVkIgogICB9LAogICAidG9waWMiOiIv c3Vic2NyaXB0aW9ucy9hYTk4OTc0Yi01ZDJhLTRkOTgtYTc4YS0zODJmMzcxNWQwN2UiCn0=""" # run with real match host.run_policies_for_event(message) add_job_mock.assert_called_with( ANY, id='one619d2674-b396-4356-9619-6c5a52fe4e88', name='one', args=ANY, misfire_grace_time=ANY) add_job_mock.reset_mock() # run with no match host.policies = {} host.run_policies_for_event(message) self.assertFalse(add_job_mock.called)
def mock_message(success): m = QueueMessage() m.id = uuid4() m.insertion_time = time.time() m.expiration_time = None m.dequeue_count = None if success: content = { "OperationId": str(m.id), "Database": "db1", "Table": "table1", "IngestionSourceId": str(m.id), "IngestionSourcePath": "blob/path", "RootActivityId": "1", "SucceededOn": time.time(), } else: content = { "OperationId": str(m.id), "Database": "db1", "Table": "table1", "IngestionSourceId": str(m.id), "IngestionSourcePath": "blob/path", "RootActivityId": "1", "FailedOn": time.time(), "Details": "", "ErrorCode": "1", "FailureStatus": "", "OriginatesFromUpdatePolicy": "", "ShouldRetry": False, } m.content = str( base64.b64encode( json.dumps(content).encode("utf-8")).decode("utf-8")) m.pop_receipt = None m.time_next_visible = None return m
async def update_message( self, message, visibility_timeout=None, pop_receipt=None, # type: ignore content=None, timeout=None, **kwargs): # type: (Any, int, Optional[str], Optional[Any], Optional[int], Any) -> QueueMessage """Updates the visibility timeout of a message. You can also use this operation to update the contents of a message. This operation can be used to continually extend the invisibility of a queue message. This functionality can be useful if you want a worker role to "lease" a queue message. For example, if a worker role calls :func:`~receive_messages()` and recognizes that it needs more time to process a message, it can continually extend the message's invisibility until it is processed. If the worker role were to fail during processing, eventually the message would become visible again and another worker role could process it. If the key-encryption-key field is set on the local service object, this method will encrypt the content before uploading. :param str message: The message object or id identifying the message to update. :param int visibility_timeout: Specifies the new visibility timeout value, in seconds, relative to server time. The new value must be larger than or equal to 0, and cannot be larger than 7 days. The visibility timeout of a message cannot be set to a value later than the expiry time. A message can be updated until it has been deleted or has expired. The message object or message id identifying the message to update. :param str pop_receipt: A valid pop receipt value returned from an earlier call to the :func:`~receive_messages` or :func:`~update_message` operation. :param obj content: Message content. Allowed type is determined by the encode_function set on the service. Default is str. :param int timeout: The server timeout, expressed in seconds. :return: A :class:`~azure.storage.queue.models.QueueMessage` object. For convenience, this object is also populated with the content, although it is not returned by the service. :rtype: ~azure.storage.queue.models.QueueMessage Example: .. literalinclude:: ../tests/test_queue_samples_message.py :start-after: [START update_message] :end-before: [END update_message] :language: python :dedent: 12 :caption: Update a message. """ try: message_id = message.id message_text = content or message.content receipt = pop_receipt or message.pop_receipt insertion_time = message.insertion_time expiration_time = message.expiration_time dequeue_count = message.dequeue_count except AttributeError: message_id = message message_text = content receipt = pop_receipt insertion_time = None expiration_time = None dequeue_count = None if receipt is None: raise ValueError("pop_receipt must be present") if message_text is not None: self._config.message_encode_policy.configure( self.require_encryption, self.key_encryption_key, self.key_resolver_function) message_text = self._config.message_encode_policy(message_text) updated = GenQueueMessage(message_text=message_text) else: updated = None # type: ignore try: response = await self._client.message_id.update( queue_message=updated, visibilitytimeout=visibility_timeout or 0, timeout=timeout, pop_receipt=receipt, cls=return_response_headers, queue_message_id=message_id, **kwargs) new_message = QueueMessage(content=message_text) new_message.id = message_id new_message.insertion_time = insertion_time new_message.expiration_time = expiration_time new_message.dequeue_count = dequeue_count new_message.pop_receipt = response["popreceipt"] new_message.time_next_visible = response["time_next_visible"] return new_message except StorageErrorException as error: process_storage_error(error)