示例#1
0
def requeue_dead_letter(num_messages: int = 10,
                        visibility_timeout: int = None) -> None:
    """
    Re-queues everything in the Hedwig DLQ back into the Hedwig queue.

    :param num_messages: Maximum number of messages to fetch in one SQS call. Defaults to 10.
    :param visibility_timeout: The number of seconds the message should remain invisible to other queue readers.
        Defaults to None, which is queue default
    """
    queue = get_queue(get_default_queue_name())

    dead_letter_queue = get_dead_letter_queue(queue)

    logging.info("Re-queueing messages from {} to {}".format(
        dead_letter_queue.url, queue.url))
    while True:
        queue_messages = get_queue_messages(
            dead_letter_queue,
            num_messages=num_messages,
            visibility_timeout=visibility_timeout,
            wait_timeout_s=1,
        )
        if not queue_messages:
            break

        logging.info("got {} messages from dlq".format(len(queue_messages)))

        _enqueue_messages(queue, queue_messages)
        dead_letter_queue.delete_messages(
            Entries=[{
                'Id': message.message_id,
                'ReceiptHandle': message.receipt_handle
            } for message in queue_messages])

        logging.info("Re-queued {} messages".format(len(queue_messages)))
示例#2
0
    def test_listen_for_messages(self, mock_fetch_and_process, mock_get_queue):
        num_messages = 3
        visibility_timeout_s = 4
        loop_count = 1

        listen_for_messages(num_messages, visibility_timeout_s, loop_count)

        queue_name = get_default_queue_name()
        mock_get_queue.assert_called_once_with(queue_name)
        mock_fetch_and_process.assert_called_once_with(
            queue_name,
            mock_get_queue.return_value,
            num_messages=num_messages,
            visibility_timeout=visibility_timeout_s)
示例#3
0
def test_requeue_dead_letter_failure(mock_get_queue, mock_get_queue_messages):
    num_messages = 3
    visibility_timeout = 4

    messages = [mock.MagicMock() for _ in range(num_messages)]
    mock_get_queue_messages.side_effect = iter([messages, None])
    dlq_name = f'{get_default_queue_name()}-DLQ'

    mock_queue, mock_dlq = mock.MagicMock(), mock.MagicMock()
    mock_queue.attributes = {
        'RedrivePolicy': json.dumps({'deadLetterTargetArn': dlq_name})
    }
    mock_queue.send_messages.return_value = {
        'Failed': [{
            'Id': 'string'
        }],
        'Successful': []
    }
    mock_get_queue.side_effect = iter([mock_queue, mock_dlq])

    with pytest.raises(PartialFailure) as exc_info:
        requeue_dead_letter(num_messages, visibility_timeout)

    assert exc_info.value.success_count == 0
    assert exc_info.value.failure_count == 1

    mock_get_queue.assert_has_calls([
        mock.call(get_default_queue_name()),
        mock.call(dlq_name),
    ])

    # not called a 2nd time after failure
    mock_get_queue_messages.assert_called_once_with(
        mock_dlq,
        num_messages=num_messages,
        visibility_timeout=visibility_timeout,
        wait_timeout_s=1,
    )

    mock_queue.send_messages.assert_called_once_with(
        Entries=[{
            'Id': queue_message.message_id,
            'MessageBody': queue_message.body,
            'MessageAttributes': queue_message.message_attributes
        } for queue_message in messages])

    mock_dlq.delete_messages.assert_not_called()
示例#4
0
    def extend_visibility_timeout(self, visibility_timeout_s: int) -> None:
        """
        Extends visibility timeout of a message for long running tasks.
        """
        from hedwig.consumer import get_default_queue_name

        queue_name = get_default_queue_name()

        client = _get_sqs_client()

        queue_url = _get_queue_url(client, queue_name)

        client.change_message_visibility(
            QueueUrl=queue_url,
            ReceiptHandle=self.receipt,
            VisibilityTimeout=visibility_timeout_s,
        )
def test_requeue_dead_letter(mock_get_queue, mock_get_queue_messages):
    num_messages = 3
    visibility_timeout = 4

    messages = [mock.MagicMock() for _ in range(num_messages)]
    mock_get_queue_messages.side_effect = iter([messages, None])
    dlq_name = f'{get_default_queue_name()}-DLQ'

    mock_queue, mock_dlq = mock.MagicMock(), mock.MagicMock()
    mock_queue.attributes = {'RedrivePolicy': json.dumps({'deadLetterTargetArn': dlq_name})}
    mock_queue.send_messages.return_value = {'Failed': []}
    mock_get_queue.side_effect = iter([mock_queue, mock_dlq])
    mock_dlq.delete_messages.return_value = {'Failed': []}

    requeue_dead_letter(num_messages, visibility_timeout)

    mock_get_queue.assert_has_calls([
        mock.call(get_default_queue_name()),
        mock.call(dlq_name),
    ])

    mock_get_queue_messages.assert_has_calls([
        mock.call(mock_dlq, num_messages=num_messages, visibility_timeout=visibility_timeout, wait_timeout_s=1),
        mock.call(mock_dlq, num_messages=num_messages, visibility_timeout=visibility_timeout, wait_timeout_s=1),
    ])

    mock_queue.send_messages.assert_called_once_with(
        Entries=[
            {
                'Id': queue_message.message_id,
                'MessageBody': queue_message.body,
                'MessageAttributes': queue_message.message_attributes
            }
            for queue_message in messages
        ]
    )

    mock_dlq.delete_messages.assert_called_once_with(
        Entries=[
            {
                'Id': queue_message.message_id,
                'ReceiptHandle': queue_message.receipt_handle,
            }
            for queue_message in messages
        ]
    )
示例#6
0
def test_get_default_queue_name():
    assert get_default_queue_name(
    ) == f'HEDWIG-{settings.HEDWIG_QUEUE.upper()}'