
                             S r SSKrSSKrSSKrSSKrSSKrSSKJr  SSKJ	r	   " S S\
5      rS r " S S	\
5      rS
 rSS\R                  \\" 5       S4S jrg)aH  Retry decorators for calls raising exceptions.

This module is used mostly to decorate all integration points where the code
makes calls to remote services. Searching through the code base for @retry
should find all such places. For this reason even places where retry is not
needed right now use a @retry.no_retries decorator.
    N)_exceptions)reraisec                   .    \ rS rSrSr   SS jrS rSrg)FuzzedExponentialIntervals!   a  Iterable for intervals that are exponentially spaced, with fuzzing.

On iteration, yields retry interval lengths, in seconds. Every iteration over
this iterable will yield differently fuzzed interval lengths, as long as fuzz
is nonzero.

Args:
  initial_delay_secs: The delay before the first retry, in seconds.
  num_retries: The total number of times to retry.
  factor: The exponential factor to use on subsequent retries.
    Default is 2 (doubling).
  fuzz: A value between 0 and 1, indicating the fraction of fuzz. For a
    given delay d, the fuzzed delay is randomly chosen between
    [(1 - fuzz) * d, d].
  max_delay_sec: Maximum delay (in seconds). After this limit is reached,
    further tries use max_delay_sec instead of exponentially increasing
    the time. Defaults to 5 minutes.
c                 t    Xl         X l        X0l        SUs=::  a  S::  d  O  [        S5      eX@l        XPl        g )Nr      z.Fuzz parameter expected to be in [0, 1] range.)_initial_delay_secs_num_retries_factor
ValueError_fuzz_max_delay_secs)selfinitial_delay_secsnum_retriesfactorfuzzmax_delay_secss         .lib/third_party/ml_sdk/cloud/ml/util/_retry.py__init__#FuzzedExponentialIntervals.__init__5   s7      2#L>>GHHJ)    c              #   8  #    [        U R                  U R                  5      n[        U R                  5       H]  nSU R
                  -
  [        R                  " 5       U R
                  -  -   nX-  v   [        U R                  XR                  -  5      nM_     g 7f)Nr	   )minr   r
   ranger   r   randomr   )r   current_delay_secs_fuzz_multipliers       r   __iter__#FuzzedExponentialIntervals.__iter__C   s{     T1143K3KL4$$%DJJ4::)EEo00t331LL@B &s   BB)r   r   r
   r   r   N)         ?   )__name__
__module____qualname____firstlineno____doc__r   r!   __static_attributes__ r   r   r   r   !   s    ,  *Br   r   c                 f    [        U [        R                  5      (       a  U R                  S:  a  ggg)z<Filter allowing retries on server errors and non-HttpErrors.i  TF)
isinstancer   _RequestExceptionstatus)	exceptions    r   retry_on_server_errors_filterr2   L   s.    	;88993 r   c                       \ rS rSrSrS rSrg)ClockY   z$A simple clock implementing sleep().c                 0    [         R                  " U5        g )N)timesleep)r   values     r   r8   Clock.sleep\   s    JJur   r,   N)r&   r'   r(   r)   r*   r8   r+   r,   r   r   r4   r4   Y   s
    ,r   r4   c                 $    [        S SS9" U 5      $ )z:A retry decorator for places where we do not want retries.c                     g)NFr,   )r   s    r   <lambda>no_retries.<locals>.<lambda>b   s    r   N)retry_filterclock)with_exponential_backoff)funs    r   
no_retriesrC   `   s    	!d	KC	PPr   
   r	   Tc                 (   ^ ^^^^^ UUUUU U4S jnU$ )a~  Decorator with arguments that control the retry logic.

Args:
  num_retries: The total number of times to retry.
  initial_delay_secs: The delay before the first retry, in seconds.
  logger: A callable used to report en exception. Must have the same signature
    as functions in the standard logging module. The default is
    logging.warning.
  retry_filter: A callable getting the exception raised and returning True
    if the retry should happen. For instance we do not want to retry on
    404 Http errors most of the time. The default value will return true
    for server errors (HTTP status code >= 500) and non Http errors.
  clock: A clock object implementing a sleep method. The default clock will
    use time.sleep().
  fuzz: True if the delay should be fuzzed (default). During testing False
    can be used so that the delays are not randomized.

Returns:
  As per Python decorators with arguments pattern returns a decorator
  for the function which in turn will return the wrapped (decorated) function.

The decorator is intended to be used on callables that make HTTP or RPC
requests that can temporarily timeout or have transient errors. For instance
the make_http_request() call below will be retried 16 times with exponential
backoff and fuzzing of the delay interval (default settings).

from cloudml.util import retry
# ...
@retry.with_exponential_backoff()
make_http_request(args)
c                 Z   >^ ^ [        [        TTT(       a  SOSS95      mUU UUU4S jnU$ )zCThe real decorator whose purpose is to return the wrapped function.r$   r   )r   c                    >   T" U 0 UD6$ ! [          Ga@  nT" U5      (       d  e [        R                  " 5       S   n  [        T	5      nO%! [         a    [        [        U5      X#5         Of = fT" SW[        TS[        T5      5      SR                  [        R                  " UR                  U5      5      SR                  [        R                  " U5      5      5        TR                  U5        [        R                  S:  a  [        R                   " 5         S n S nAO8! [        R                  S:  a  [        R                   " 5         S nf = fS nAff = fGMZ  )Nr#   zRetry with exponential backoff: waiting for %s seconds before retrying %s because we caught exception: %s Traceback for above exception (most recent call last):
%sr&    )   r   )	Exceptionsysexc_infonextStopIterationr   typegetattrstrjoin	tracebackformat_exception_only	__class__	format_tbr8   version_info	exc_clear)
argskwargsexnexn_tracebacksleep_intervalr@   rB   loggerr?   retry_intervalss
        r   wrapperAwith_exponential_backoff.<locals>.real_decorator.<locals>.wrapper   s%   	!d%f%
% 	!c"" ,,.+-!5#O4n  5d3i45 M ZS2	77sKL	++M:;= KK'
 &(mmo M &(mmo M;	! sJ    E&EA
D"A-*D",A--BD"2+E"-EEE)iterr   )	rB   r`   r_   r@   r   r   r^   r   r?   s	   ` @r   real_decorator0with_exponential_backoff.<locals>.real_decorator   s6     "#1	FGO!! !!F Nr   r,   )r   r   r^   r?   r@   r   rc   s   `````` r   rA   rA   e   s    L* *X 
r   )r*   loggingr   rK   r7   rS   google.cloud.ml.utilr   sixr   objectr   r2   r4   rC   warningrA   r,   r   r   <module>rj      sg      
   , (B (BV
F Q
 *,01$+OO*G#(7"&Rr   