def message_handler(message_json: str, receipt: typing.Optional[str]) -> None: try: message_body = json.loads(message_json) message = Message(message_body) except (ValidationError, ValueError): log_invalid_message(message_json) raise log_received_message(message_body) try: message.call_task(receipt) except IgnoreException: logger.info(f'Ignoring task {message.id}') return except LoggingException as e: # log with message and extra logger.exception(str(e), extra=e.extra) # let it bubble up so message ends up in DLQ raise except RetryException: # Retry without logging exception logger.info('Retrying due to exception') # let it bubble up so message ends up in DLQ raise except Exception: logger.exception(f'Exception while processing message') # let it bubble up so message ends up in DLQ raise
def test_validate_missing_data(self, missing_data, message_data): if missing_data.startswith('metadata__'): message_data['metadata'][missing_data.split('__')[1]] = None else: message_data[missing_data] = None with pytest.raises(ValidationError): Message(message_data).validate()
def test_create_metadata(self, mock_time): mock_time.return_value = time.time() assert Message._create_metadata() == { 'priority': Priority.default.name, 'timestamp': int(mock_time.return_value * 1000), 'version': Message.CURRENT_VERSION, }
def test_new(self, message_data): message = Message.new( message_data['task'], message_data['args'], message_data['kwargs'], message_data['id'], message_data['headers'], ) assert message.id == message_data['id'] assert message.headers == message_data['headers'] assert message.task_name == message_data['task'] assert message.args == message_data['args'] assert message.kwargs == message_data['kwargs']
def publish(message: Message) -> None: """ Publishes a message on Taskhawk queue """ message_body = message.as_dict() payload = _convert_to_json(message_body) if settings.IS_LAMBDA_APP: topic = _get_sns_topic(message.priority) _publish_over_sns(topic, payload, message.headers) else: queue_name = get_queue_name(message.priority) queue = get_queue(queue_name) _publish_over_sqs(queue, payload, message.headers) _log_published_message(message_body)
def test_validate_missing_task(self, _, message_data): with pytest.raises(ValidationError): Message(message_data).validate()
def test_validate_invalid_version(self, message_data): message_data['metadata']['version'] = '2.0' with pytest.raises(ValidationError): Message(message_data).validate()
def _load_and_validate_message(data: dict) -> Message: message = Message(data) message.validate() return message
def test_validate_bad_timestamp(self, message_data): message_data['metadata']['timestamp'] = 'foobar' with pytest.raises(ValidationError): Message(message_data).validate()
def test_validate_str_timestamp(self, message_data): message_data['metadata']['timestamp'] = '2015-11-11T21:29:54Z' Message(message_data).validate()
def _message_with_decimal(message_data): message_data = copy.deepcopy(message_data) message_data['args'][0] = Decimal(1469056316326) return Message(message_data)
def test__convert_to_json_non_serializable(message_data): message_data['args'][0] = object() message = Message(message_data) with pytest.raises(TypeError): _convert_to_json(message.as_dict())
def test__convert_to_json_decimal(value, message_data): message_data['args'][0] = Decimal(value) message = Message(message_data) assert json.loads(_convert_to_json(message.as_dict()))['args'][0] == float( message.args[0])