예제 #1
0
    def read(self):
        """Return an item."""
        if self._run:
            raise Abort('testing', {})

        self._run = True
        return 1
예제 #2
0
async def _retry(app, message, exc):
    """Retry the message.

    An exception that is included as a retryable type will result in the
    message being retried so long as the threshold and timeout haven't
    been reached.

    Args:
        app (henson.base.Application): The current application.
        message (dict): The message to be retried.
        exc (Exception): The exception that caused processing the
            message to fail.

    Raises:
        Abort: If the message is scheduled to be retried.

    """
    if not isinstance(exc, app.settings['RETRY_EXCEPTIONS']):
        # If the exception raised isn't retryable, return control so the
        # next error callback can be called.
        return

    settings = _get_settings(app, exc)

    retry_info = _retry_info(message)

    threshold = settings['RETRY_THRESHOLD']
    if _exceeded_threshold(retry_info['count'], threshold):
        # If we've exceeded the number of times to retry the message,
        # don't retry it again.
        return

    timeout = settings['RETRY_TIMEOUT']
    if _exceeded_timeout(retry_info['start_time'], timeout):
        # If we've gone past the time to stop retrying, don't retry it
        # again.
        return

    if settings['RETRY_DELAY']:
        # If a delay has been specified, calculate the actual delay
        # based on any backoff and then sleep for that long. Add the
        # delay time to the retry information so that it can be used
        # to gain insight into the full history of a retried message.
        retry_info['delay'] = _calculate_delay(
            delay=settings['RETRY_DELAY'],
            backoff=settings['RETRY_BACKOFF'],
            number_of_retries=retry_info['count'],
        )
        await asyncio.sleep(retry_info['delay'])

    # Update the retry information and retry the message.
    retry_info['count'] += 1
    message['_retry'] = retry_info
    await settings['RETRY_CALLBACK'](app, message)

    # If the exception was retryable, none of the other callbacks should
    # execute.
    raise Abort('message.retried', message)
예제 #3
0
 async def read(self):
     nonlocal consumer_called
     consumer_called = True
     raise Abort('reason', 'message')
예제 #4
0
        'RETRY_BACKOFF', None) == backoff
    assert test_app.settings['RETRY_OVERRIDES'][exception].get(
        'RETRY_CALLBACK', None) == callback_arg
    assert test_app.settings['RETRY_OVERRIDES'][exception].get(
        'RETRY_DELAY', None) == delay
    assert test_app.settings['RETRY_OVERRIDES'][exception].get(
        'RETRY_THRESHOLD', None) == threshold
    assert test_app.settings['RETRY_OVERRIDES'][exception].get(
        'RETRY_TIMEOUT', None) == timeout


@pytest.mark.parametrize(
    'exc, expected, excs',
    (
        (KeyError('test KeyError'), 1.1, (OSError, KeyError, Abort)),
        (Abort('test', {}), 1.1, (OSError, Abort)),

        # Confirm we can handle a single exception and not a tuple
        (OSError('test OSError'), 1.05, OSError),

        # Test that inheritance is working properly
        (TestRetryChildAException(), 2.05, TestRetryParentException),
        (TestRetryGrandchildException(), 2.05, TestRetryParentException),
        (TestRetryChildBException(), 3.05, TestRetryParentException),
        (TestRetryRedHerringException(), 1.1, TestRetryParentException)))
@pytest.mark.asyncio
async def test_get_settings(test_app: Application, coroutine: Coroutine,
                            exc: Exception, excs, expected: bool):
    """Test that _get_settings is grabbing the proper settings working."""
    test_app.settings['RETRY_CALLBACK'] = coroutine
    test_app.settings['RETRY_BACKOFF'] = 1.1