Exemple #1
0
    def __init__(
        self,
        when=None,
        max_attempts=None,
        on_exception=None,
        stop=None,
        backoff=None,
    ):
        if stop is None:
            if max_attempts is not None:
                stop = stop_mod.after_attempt(max_attempts)
            else:
                stop = stop_mod.NEVER

        if on_exception is not None:
            when = when_mod.raises(on_exception) | when

        if when is None:
            when = self._DEFAULT_PREDICATE

        if backoff is None:
            backoff = backoff_mod.jittered()

        if not isinstance(backoff, backoff_mod.RetryBackoff):
            backoff = backoff_mod.from_iterable_factory(backoff)

        self._when = when
        self._backoff = backoff
        self._stop = stop
Exemple #2
0
def test_when_or_operator_with_exception(mocker, request_builder):
    # Setup
    response = mocker.Mock()
    response.status_code = 401
    predicate = when.status(401) | when.raises(retry.BASE_CLIENT_EXCEPTION)

    # Verify: Calls __call__ for both predicates
    request_builder.client.exceptions.BaseClientException = RuntimeError
    predicate = predicate(request_builder)

    # Verify: when left predicate matches
    assert predicate.should_retry_after_response(response) is True

    # Verify: when right predicate matches
    assert (predicate.should_retry_after_exception(
        RuntimeError, RuntimeError(), None) is True)

    # Verify: when neither matches
    assert (predicate.should_retry_after_exception(Exception, Exception(),
                                                   None) is False)
Exemple #3
0
    def __init__(
        self,
        when=None,
        max_attempts=None,
        on_exception=None,
        stop=None,
        backoff=None,
    ):
        if stop is not None:
            self._stop = stop
        elif max_attempts is not None:
            self._stop = stop_mod.after_attempt(max_attempts)
        else:
            self._stop = stop_mod.DISABLE

        self._predicate = when

        if on_exception is not None:
            self._predicate = when_mod.raises(on_exception) | self._predicate

        if self._predicate is None:
            self._predicate = self._DEFAULT_PREDICATE

        self._backoff = backoff_mod.jittered() if backoff is None else backoff
from anacreonlib.types.request_datatypes import *
from anacreonlib.types.response_datatypes import (
    AuthenticationResponse,
    convert_json_to_anacreon_obj,
    AnacreonObject,
    handle_hexarc_error_response,
)
from anacreonlib.types.scenario_info_datatypes import (
    ScenarioInfo,
    convert_json_to_scenario_info,
)


@uplink.timeout(10)
@uplink.retry(when=raises(retry.CONNECTION_TIMEOUT))
@uplink.json
@returns.json
@handle_hexarc_error_response
class AnacreonAsyncClient(Consumer):
    """
    A coroutine-based asynchronous API client to interact with anacreon
    """
    def __init__(
            self,
            *,
            base_url: str = "https://anacreon.kronosaur.com/api/") -> None:
        self._aio_session = aiohttp.ClientSession()
        super().__init__(
            base_url=base_url,
            client=clients.AiohttpClient(session=self._aio_session),
Exemple #5
0
class retry(decorators.MethodAnnotation):
    """
    A decorator that adds retry support to a consumer method or to an
    entire consumer.

    Unless you specify the ``when`` or ``on_exception`` argument, all
    failed requests that raise an exception are retried.

    Unless you specify the ``max_attempts`` or ``stop`` argument, this
    decorator continues retrying until the server returns a response.

    Unless you specify the ``backoff`` argument, this decorator uses
    `capped exponential backoff and jitter <https://amzn.to/2xc2nK2>`_,
    which should benefit performance with remote services under high
    contention.

    Args:
        when (optional): A predicate that determines when a retry
            should be attempted.
        max_attempts (int, optional): The number of retries to attempt.
            If not specified, requests are retried continuously until
            a response is rendered.
        on_exception (:class:`Exception`, optional): The exception type
            that should prompt a retry attempt.
        stop (:obj:`callable`, optional): A function that creates
            predicates that decide when to stop retrying a request.
        backoff (:obj:`callable`, optional): A function that creates
            an iterator over the ordered sequence of timeouts between
            retries. If not specified, exponential backoff is used.
    """

    _DEFAULT_PREDICATE = when_mod.raises(Exception)

    def __init__(
        self,
        when=None,
        max_attempts=None,
        on_exception=None,
        stop=None,
        backoff=None,
    ):
        if stop is not None:
            self._stop = stop
        elif max_attempts is not None:
            self._stop = stop_mod.after_attempt(max_attempts)
        else:
            self._stop = stop_mod.DISABLE

        self._predicate = when

        if on_exception is not None:
            self._predicate = when_mod.raises(on_exception) | self._predicate

        if self._predicate is None:
            self._predicate = self._DEFAULT_PREDICATE

        self._backoff = backoff_mod.jittered() if backoff is None else backoff

    BASE_CLIENT_EXCEPTION = ClientExceptionProxy(
        lambda ex: ex.BaseClientException)
    CONNECTION_ERROR = ClientExceptionProxy(lambda ex: ex.ConnectionError)
    CONNECTION_TIMEOUT = ClientExceptionProxy(lambda ex: ex.ConnectionTimeout)
    SERVER_TIMEOUT = ClientExceptionProxy(lambda ex: ex.ServerTimeout)
    SSL_ERROR = ClientExceptionProxy(lambda ex: ex.SSLError)

    def modify_request(self, request_builder):
        request_builder.add_request_template(
            self._create_template(request_builder))

    def _create_template(self, request_builder):
        return RetryTemplate(self._backoff_iterator(),
                             self._predicate(request_builder))

    def _backoff_iterator(self):
        stop_gen = self._stop()
        for delay in self._backoff():
            next(stop_gen)
            if stop_gen.send(delay):
                break
            yield delay

    stop = stop_mod
    backoff = backoff_mod
    when = when_mod
Exemple #6
0
class retry(decorators.MethodAnnotation):
    """
    A decorator that adds retry support to a consumer method or to an
    entire consumer.

    Unless you specify the ``when`` or ``on_exception`` argument, all
    failed requests that raise an exception are retried.

    Unless you specify the ``max_attempts`` or ``stop`` argument, this
    decorator continues retrying until the server returns a response.

    Unless you specify the ``backoff`` argument, this decorator uses
    `capped exponential backoff and jitter <https://amzn.to/2xc2nK2>`_,
    which should benefit performance with remote services under high
    contention.

    .. note::

        Response and error handlers (see :ref:`here <custom response
        handler>`) are invoked after the retry condition breaks or all
        retry attempts are exhausted, whatever comes first. These
        handlers will receive the first response/exception that triggers
        the retry's ``stop`` condition or doesn't match its ``when``
        filter.

        In other words, responses or exceptions that match
        the retry condition (e.g., retry when status code is 5xx) are
        not subject to response or error handlers as long as the request
        doesn't break the retry's stop condition (e.g., stop retrying
        after 5 attempts).

    Args:
        when (optional): A predicate that determines when a retry
            should be attempted.
        max_attempts (int, optional): The number of retries to attempt.
            If not specified, requests are retried continuously until
            a response is rendered.
        on_exception (:class:`Exception`, optional): The exception type
            that should prompt a retry attempt.
        stop (:obj:`callable`, optional): A function that creates
            predicates that decide when to stop retrying a request.
        backoff (:class:`RetryBackoff`, :obj:`callable`, optional): A
            backoff strategy or a function that creates an iterator
            over the ordered sequence of timeouts between retries. If
            not specified, exponential backoff is used.
    """

    _DEFAULT_PREDICATE = when_mod.raises(Exception)

    stop = stop_mod
    backoff = backoff_mod
    when = when_mod

    def __init__(
        self,
        when=None,
        max_attempts=None,
        on_exception=None,
        stop=None,
        backoff=None,
    ):
        if stop is None:
            if max_attempts is not None:
                stop = stop_mod.after_attempt(max_attempts)
            else:
                stop = stop_mod.NEVER

        if on_exception is not None:
            when = when_mod.raises(on_exception) | when

        if when is None:
            when = self._DEFAULT_PREDICATE

        if backoff is None:
            backoff = backoff_mod.jittered()

        if not isinstance(backoff, backoff_mod.RetryBackoff):
            backoff = backoff_mod.from_iterable_factory(backoff)

        self._when = when
        self._backoff = backoff
        self._stop = stop

    BASE_CLIENT_EXCEPTION = ClientExceptionProxy(
        lambda ex: ex.BaseClientException
    )
    CONNECTION_ERROR = ClientExceptionProxy(lambda ex: ex.ConnectionError)
    CONNECTION_TIMEOUT = ClientExceptionProxy(lambda ex: ex.ConnectionTimeout)
    SERVER_TIMEOUT = ClientExceptionProxy(lambda ex: ex.ServerTimeout)
    SSL_ERROR = ClientExceptionProxy(lambda ex: ex.SSLError)

    def modify_request(self, request_builder):
        request_builder.add_request_template(
            _RetryTemplate(
                self._when(request_builder),
                self._backoff,
                self._stop,
            )
        )