
    V-                     >   S r SSKJr  SSKJr  SSKJr  SSKrSSK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   \R                  rSr " S S	\5      r " S
 S\5      r " S S\5      r " S S\5      r " S S\5      rSSSSS\SS4S jrS rS rg! \ a    \r NWf = f)z!Implementation of retrying logic.    )absolute_import)division)unicode_literalsN)
exceptions  c                       \ rS rSrSrS rSrg)RetryerState*   z+Object that holds the state of the retryer.c                 (    Xl         X l        X0l        g)ah  Initializer for RetryerState.

Args:
  retrial: int, the retry attempt we are currently at.
  time_passed_ms: int, number of ms that passed since we started retryer.
  time_to_wait_ms: int, number of ms to wait for the until next trial.
      If this number is -1, it means the iterable item that specifies the
      next sleep value has raised StopIteration.
Nretrialtime_passed_mstime_to_wait_ms)selfr   r   r   s       %lib/googlecloudsdk/core/util/retry.py__init__RetryerState.__init__-   s     L(*    r   N)__name__
__module____qualname____firstlineno____doc__r   __static_attributes__ r   r   r	   r	   *   s
    3+r   r	   c                   2   ^  \ rS rSrSrU 4S jrS rSrU =r$ )RetryException<   z#Raised to stop retrials on failure.c                 P   > Xl         X l        X0l        [        [        U ]  U5        g N)messagelast_resultstatesuperr   r   )r   r!   r"   r#   	__class__s       r   r   RetryException.__init__?   s"    L"J	.$(1r   c                     SR                  U R                  U R                  R                  U R                  R                  U R                  R
                  S9$ )Nzvlast_result={last_result}, last_retrial={last_retrial}, time_passed_ms={time_passed_ms},time_to_wait={time_to_wait_ms})r"   last_retrialr   r   )formatr"   r#   r   r   r   )r   s    r   __str__RetryException.__str__E   sK    --3V ,,!ZZ//#zz88 $

 : :	 .4 .<=r   )r"   r!   r#   )	r   r   r   r   r   r   r*   r   __classcell__)r%   s   @r   r   r   <   s    +2= =r   r   c                       \ rS rSrSrSrg)WaitExceptionO   z Raised when timeout was reached.r   Nr   r   r   r   r   r   r   r   r   r.   r.   O   s    (r   r.   c                       \ rS rSrSrSrg)MaxRetrialsExceptionS   z&Raised when too many retrials reached.r   Nr0   r   r   r   r2   r2   S   s    .r   r2   c                   V    \ rS rSrSrSSS\SS4S jrS rS r  S
S jr	  S
S jr
S	rg)RetryerW   z5Retries a function based on specified retry strategy.Nc                 L    Xl         X l        X0l        X@l        XPl        X`l        g)a  Initializer for Retryer.

Args:
  max_retrials: int, max number of retrials before raising RetryException.
  max_wait_ms: int, number of ms to wait before raising
  exponential_sleep_multiplier: float, The exponential factor to use on
      subsequent retries.
  jitter_ms: int, random [0, jitter_ms] additional value to wait.
  status_update_func: func(result, state) called right after each trial.
  wait_ceiling_ms: int, maximum wait time between retries, regardless of
      modifiers added like exponential multiplier or jitter.
N)_max_retrials_max_wait_ms_exponential_sleep_multiplier
_jitter_ms_status_update_func_wait_ceiling_ms)r   max_retrialsmax_wait_msexponential_sleep_multiplier	jitter_msstatus_update_funcwait_ceiling_mss          r   r   Retryer.__init__Z   s'      &#)E&O1+r   c                     U R                   b&  U R                   UR                  ::  a  [        SX5      eU R                  b4  UR                  UR
                  -   U R                  :  a  [        SX5      eg g )NReachedTimeout)r8   r   r2   r9   r   r   r.   )r   resultr#   s      r   _RaiseIfStopRetryer._RaiseIfStopq   so    %$*<*<*M F::$			 5 5	58I8I	IIv55 
J %r   c                    UnU(       a  U R                   (       aM  SnU R                   S:  a*  U[        R                  " XC-  U R                   5      :  a  UnOX0R                   U-  -  nU R                  (       a%  U[        R                  " 5       U R                  -  -  nU R
                  (       a  [        X0R
                  5      nU$ g)aq  Get time to wait after applying modifyers.

Apply the exponential sleep multiplyer, jitter and ceiling limiting to the
base sleep time.

Args:
  last_retrial: int, which retry attempt we just tried. First try this is 0.
  sleep_ms: int, how long to wait between the current trials.

Returns:
  int, ms to wait before trying next attempt with all waiting logic applied.
l    0jyg      ?r   )r:   mathlogr;   randomr=   min)r   r(   sleep_mswait_time_mshundred_years_mss        r   _GetTimeToWaitRetryer._GetTimeToWaitx   s     L		+	+ .--3txx+..H0 90 *,
<<L
L,	$//99			<)>)>?r   c                    ^^^^ Tb  TOSmTb  TO0 mUUU4S jnTc  S nOU4S jnUnU R                  XgUS9u  pU
(       a  [        R                  " U
S   U
S   S9  U	$ )	a"  Retries the function if an exception occurs.

Args:
  func: The function to call and retry.
  args: a sequence of positional arguments to be passed to func.
  kwargs: a dictionary of positional arguments to be passed to func.
  should_retry_if: func(exc_type, exc_value, exc_traceback, state) that
      returns True or False.
  sleep_ms: int or iterable for how long to wait between trials.

Returns:
  Whatever the function returns.

Raises:
  RetryException, WaitException: if function is retries too many times,
    or time limit is reached.
r   c                  V   >  T" T 0 TD6S 4$ !   S [         R                  " 5       4s $ = fr    )sysexc_info)argsfunckwargss   r   TryFunc)Retryer.RetryOnException.<locals>.TryFunc   s5    $T$V$d**$S\\^##s   	 (c                     U S   S L$ )N   r   )xss     r   <lambda>*Retryer.RetryOnException.<locals>.<lambda>   s    !A$d"2r   c                 >   > U S   nUc  gT" US   US   US   U5      $ )Nr_   Fr      r   )try_func_resultr#   rX   should_retry_ifs      r   ShouldRetryFunc1Retryer.RetryOnException.<locals>.ShouldRetryFunc   s3    "1%x{HQK!eLLr   )rg   rP   r_   re   tb)RetryOnResultr   reraise)r   rZ   rY   r[   rg   rP   r\   should_retryrh   rH   rX   s    ````      r   RetryOnExceptionRetryer.RetryOnException   sz    ( #4D)VrF$ 2lM %l)) * BF!!5Mr   c                 Z  ^ Ub  UOSnUb  UO0 n[        5       nSn[        T5      (       a  TnOU4S jn[        U[        R                  5      (       a  [        U5      n	O[        R                  " U5      n	 U" U0 UD6n
[        5       U-
  n [        U	5      nU R                  X|5      n[        X{U5      nU" X5      (       d  U
$ US:X  a  [        SX5      eU R                  (       a  U R                  X5        U R                  X5        [        U5        US-  nM  ! [         a    Sn Nf = f)a;  Retries the function if the given condition is satisfied.

Args:
  func: The function to call and retry.
  args: a sequence of arguments to be passed to func.
  kwargs: a dictionary of positional arguments to be passed to func.
  should_retry_if: result to retry on or func(result, RetryerState) that
      returns True or False if we should retry or not.
  sleep_ms: int or iterable, for how long to wait between trials.

Returns:
  Whatever the function returns.

Raises:
  MaxRetrialsException: function retried too many times.
  WaitException: time limit is reached.
r   r   c                    > U T:H  $ r    r   )r`   ra   rg   s     r   rb   'Retryer.RetryOnResult.<locals>.<lambda>   s
    !"6r   zSleep iteration stopr_   )_GetCurrentTimeMscallable
isinstancecollections_abcIterableiter	itertoolsrepeatnextrS   StopIterationr	   r2   r<   rI   _SleepMs)r   rZ   rY   r[   rg   rP   start_time_msr   rn   	sleep_genrH   r   sleep_from_genr   r#   s       `          r   rl   Retryer.RetryOnResult   s.   & #4D)VrF%'MG  $l6l(O4455x.i""8,i
T$V$f(*]:nGi --gF7ODe&((	B	"#96II		!	!  /
&lg) 
  s   D D*)D*)r:   r;   r8   r9   r<   r=   )NNNN)r   r   r   r   r   _DEFAULT_JITTER_MSr   rI   rS   ro   rl   r   r   r   r   r5   r5   W   s@    ="&D,0<N"&,.6#J 6:6:-^ 37376r   r5   c                    ^ ^^^^^^^ T c  [         R                  " [        TTTTTTTS9$ [         R                  " T 5      UU UUUUUU4S j5       nU$ )a  A decorator to retry on exceptions.

Args:
  f: a function to run possibly multiple times
  max_retrials: int, max number of retrials before raising RetryException.
  max_wait_ms: int, number of ms to wait before raising
  sleep_ms: int or iterable, for how long to wait between trials.
  exponential_sleep_multiplier: float, The exponential factor to use on
      subsequent retries.
  jitter_ms: int, random [0, jitter_ms] additional value to wait.
  status_update_func: func(result, state) called right after each trail.
  should_retry_if: func(exc_type, exc_value, exc_traceback, state) that
      returns True or False.

Returns:
  A version of f that is executed potentially multiple times and that
  yields the first returned value or the last exception raised.
)r@   rA   r>   r?   rg   rP   rB   c                     > [        TT	TTTS9n UR                  TXT
TS9$ ! [         a4  nUR                  S   n[        R
                  " US   US   S9   S nAg S nAff = f)N)r>   r?   r@   rA   rB   )rY   r[   rg   rP   r_   re   rj   )r5   ro   r2   r"   r   rm   )rY   r[   retryermre
to_reraiser@   frA   r>   r?   rg   rP   rB   s        r   DecoratedFunction+RetryOnException.<locals>.DecoratedFunction*  s{    !%A-/G:%%ad6E/7 & 9 9   :??1%jA:a=9:s   " 
A *AA )	functoolspartialro   wraps)	r   r>   r?   rP   r@   rA   rB   rg   r   s	   ```````` r   ro   ro     sa    0 Y %A!'-/ / ??1: : : 
r   c                  D    [        [        R                  " 5       S-  5      $ )Nr   )inttimer   r   r   ru   ru   =  s    	TYY[4	  r   c                 6    [         R                  " U S-  5        g )Ng     @@)r   sleep)r   s    r   r   r   A  s    **_v%&r   )r   
__future__r   r   r   collectionsr   r{   rL   rN   rW   r   googlecloudsdk.corer   abcrx   AttributeErrorr   objectr	   	Exceptionr   r.   r2   r5   ro   ru   r   r   r   r   <module>r      s     ( &  '      
  * OO/
  +6 +$=Y =&)N )/> /kf k\ $D"1(,%)	5p!'}   / s   B BB