예제 #1
0
def _exponential_timeout_generator(initial, maximum, multiplier, deadline):
    """A generator that yields exponential timeout values.

    Args:
        initial (float): The initial timeout.
        maximum (float): The maximum timeout.
        multiplier (float): The multiplier applied to the timeout.
        deadline (float): The overall deadline across all invocations.

    Yields:
        float: A timeout value.
    """
    if deadline is not None:
        deadline_datetime = (datetime_helpers.utcnow() +
                             datetime.timedelta(seconds=deadline))
    else:
        deadline_datetime = datetime.datetime.max

    timeout = initial
    while True:
        now = datetime_helpers.utcnow()
        yield min(
            # The calculated timeout based on invocations.
            timeout,
            # The set maximum timeout.
            maximum,
            # The remaining time before the deadline is reached.
            float((deadline_datetime - now).seconds))
        timeout = timeout * multiplier
예제 #2
0
def retry_target(target, predicate, sleep_generator, deadline, on_error=None):
    """Call a function and retry if it fails.

    This is the lowest-level retry helper. Generally, you'll use the
    higher-level retry helper :class:`Retry`.

    Args:
        target(Callable): The function to call and retry. This must be a
            nullary function - apply arguments with `functools.partial`.
        predicate (Callable[Exception]): A callable used to determine if an
            exception raised by the target should be considered retryable.
            It should return True to retry or False otherwise.
        sleep_generator (Iterator[float]): An infinite iterator that determines
            how long to sleep between retries.
        deadline (float): How long to keep retrying the target.
        on_error (Callable): A function to call while processing a retryable
            exception.  Any error raised by this function will *not* be
            caught.

    Returns:
        Any: the return value of the target function.

    Raises:
        google.api.core.RetryError: If the deadline is exceeded while retrying.
        ValueError: If the sleep generator stops yielding values.
        Exception: If the target raises a method that isn't retryable.
    """
    if deadline is not None:
        deadline_datetime = (datetime_helpers.utcnow() +
                             datetime.timedelta(seconds=deadline))
    else:
        deadline_datetime = None

    last_exc = None

    for sleep in sleep_generator:
        try:
            return target()

        # pylint: disable=broad-except
        # This function explicitly must deal with broad exceptions.
        except Exception as exc:
            if not predicate(exc):
                raise
            last_exc = exc
            if on_error is not None:
                on_error(exc)

        now = datetime_helpers.utcnow()
        if deadline_datetime is not None and deadline_datetime < now:
            six.raise_from(
                exceptions.RetryError(
                    'Deadline of {:.1f}s exceeded while calling {}'.format(
                        deadline, target), last_exc), last_exc)

        _LOGGER.debug('Retrying due to {}, sleeping {:.1f}s ...'.format(
            last_exc, sleep))
        time.sleep(sleep)

    raise ValueError('Sleep generator stopped yielding sleep values.')
def test_utcnow():
    result = datetime_helpers.utcnow()
    assert isinstance(result, datetime.datetime)