
    Ѯh!                        d Z ddlmZ ddlZddlZddlZddlZddlZddl	m
Z
mZmZmZmZmZ ddlZddlZddlZ ej&                  e      Z G d d      Z G d dej.                        Zy)	zeInternal retry logic module

This module provides utilities for adding retry logic to HTTPX requests
    )annotationsN)AnyCallableListOptionalTuple	Coroutinec                      e Zd ZdZ eg d      ZdZdddedddf	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZdd	Zdd
Z	ddZ
ddZddZd ZddZddZ	 	 d	 	 	 	 	 	 	 ddZy)
HttpxRetryzHTTPX based retry config)i  i    x   
   Nr   Fc                    || _         || _        || _        || _        || _        |r|| _        || _        y g | _        || _        y N)retries_leftstatus_forcelistbackoff_factorbackoff_maxbackoff_jitterhistoryrespect_retry_after_header)selfmax_retriesr   r   r   r   r   r   s           g/home/www/academy-backend.kofcorporation.com/venv/lib/python3.12/site-packages/firebase_admin/_retry.py__init__zHttpxRetry.__init__*   sR     ( 0,&,"DL +E' DL*D'    c                ,    t        j                  |       S )z%Creates a deep copy of this instance.)copydeepcopyr   s    r   r   zHttpxRetry.copyC   s    }}T""r   c                    | j                   r|j                  | j                   v ryt        |j                  j	                  d            }| j
                  r|r|j                  | j                  v ryy)zODetermine if a response implies that the request should be retried if possible.TRetry-AfterF)r   status_codeboolheadersgetr   RETRY_AFTER_STATUS_CODES)r   responsehas_retry_afters      r   is_retryable_responsez HttpxRetry.is_retryable_responseG   sb      X%9%9T=R=R%Rx//33MBC//#((D,I,IIr   c                     | j                   dk  S )z,Determine if there are anymore more retires.r   )r   r    s    r   is_exhaustedzHttpxRetry.is_exhaustedV   s       1$$r   c                @   t        j                  d|      rt        |      }not        j                  j                  |      }|t        j                  d|       t        j                  j                  |      }|t        j                         z
  }t        |d      }|S )z9Parses Retry-After string into a float with unit seconds.z^\s*[0-9]+\s*$zInvalid Retry-After header: r   )rematchintemailutilsparsedate_tzhttpxRemoteProtocolError	mktime_tztimemax)r   retry_after_headersecondsretry_date_tuple
retry_dates        r   _parse_retry_afterzHttpxRetry._parse_retry_after\   s     88%'9:,-G${{778JK'//2NOaNb0cdd../?@J 499;.Ggq/r   c                b    |j                   j                  dd      }|r| j                  |      S y)zFDetermine the Retry-After time needed before sending the next request.r"   N)r%   r&   r=   )r   r(   r9   s      r   get_retry_afterzHttpxRetry.get_retry_aftern   s3    %--11-F**+=>>r   c           	        t        | j                        }|dk  ry| j                  d|dz
  z  z  }| j                  r$|t	        j                         | j                  z  z  }t        t        dt        | j                  |                  S )zBDetermine the backoff time needed before sending the next request.   r      )	lenr   r   r   randomfloatr8   minr   )r   attempt_countbackoffs      r   get_backoff_timezHttpxRetry.get_backoff_timev   sy     DLL)A%%}Q)?@v}})<)<<<GSC 0 0':;<<r   c                   K   | j                         }t        j                  d|       t        j                  |       d{    y7 w)zKDetermine and wait the backoff time needed before sending the next request.z;Sleeping for backoff of %f seconds following failed requestN)rI   loggerdebugasynciosleep)r   rH   s     r   sleep_for_backoffzHttpxRetry.sleep_for_backoff   s6     '')RT[\mmG$$$s   ?A	AA	c                   K   | j                   rG| j                  |      }|r4t        j                  d|       t	        j
                  |       d{    y| j                          d{    y7 7 w)zCDetermine and wait the time needed before sending the next request.zFSleeping for Retry-After header of %f seconds following failed requestN)r   r?   rK   rL   rM   rN   rO   )r   r(   retry_afters      r   rN   zHttpxRetry.sleep   sf     **..x8K\ mmK000$$&&& 1&s$   AA3A/A3)A1*A31A3c                j    | xj                   dz  c_         | j                  j                  |||f       y)z0Update the retry state based on request attempt.rA   N)r   r   append)r   requestr(   errors       r   	incrementzHttpxRetry.increment   s.     	QWh67r   )r   r0   r   zOptional[List[int]]r   rE   r   rE   r   rE   r   zSOptional[List[Tuple[httpx.Request, Optional[httpx.Response], Optional[Exception]]]]r   r$   returnNone)rW   r   )r(   httpx.ResponserW   r$   )rW   r$   )r9   strrW   float | None)r(   rY   rW   r[   rW   rX   )r(   rY   rW   rX   NN)rT   httpx.Requestr(   zOptional[httpx.Response]rU   zOptional[Exception]rW   rX   )__name__
__module____qualname____doc__	frozensetr'   DEFAULT_BACKOFF_MAXr   r   r*   r,   r=   r?   rI   rO   rN   rV    r   r   r   r   "   s    "(9   "48$%!4$%
 /4EE 2E "	E
 E "EE )-E 
E2#%$
=%'  26)-	8"8 /8 '	8
 
8r   r   c                  Z    e Zd ZdZ edddgd      ZefddZddZ	 	 	 	 	 	 dd	Zdd
Z	y)HttpxRetryTransportz!HTTPX transport with retry logic.   i  r   g      ?)r   r   r   c                    || _         |j                         }|j                  ddd       t        j                  di || _        y )Nr   T)retrieshttp2re   )_retryr   updater4   AsyncHTTPTransport_wrapped_transport)r   retrykwargstransport_kwargss       r   r   zHttpxRetryTransport.__init__   sA    !;;=A => #(":":"N=M"Nr   c                j   K   | j                  || j                  j                         d {   S 7 wr   )_dispatch_with_retryro   handle_async_request)r   rT   s     r   ru   z(HttpxRetryTransport.handle_async_request   s8     ..T,,AAC C 	C Cs   *313c                :  K   | j                   j                         }d\  }}|j                         s|r|j                  |       d{    d\  }}	 t        j                  d|        ||       d{   }t        j                  d|       |r|j                  |      s|S |r||j                  |||       |j                         s|r|S |r|t        d      7 7 l# t        j                  $ r"}t        j                  d|       |}Y d}~d}~ww xY ww)zBSends a request with retry logic using a provided dispatch method.r]   Nz-Sending request in _dispatch_with_retry(): %rzReceived response: %rzReceived error: %rz:_dispatch_with_retry() ended with no response or exception)rl   r   r,   rN   rK   rL   r4   	HTTPErrorr*   rV   AssertionError)r   rT   dispatch_methodrp   r(   rU   errs          r   rt   z(HttpxRetryTransport._dispatch_with_retry   s       "$%$$& kk(+++ )OHeLgV!0!994h?
  ; ;H EOOGXu5/ $$&2 OKYZZ3 , :?? 137sT   ADC		D!C# 4C!5C# <DD!C# #D6DDDDc                T   K   | j                   j                          d {    y 7 wr   )ro   acloser    s    r   r|   zHttpxRetryTransport.aclose   s     %%,,...s   (&(N)rp   r   rq   r   rW   rX   )rT   r^   rW   rY   )rT   r^   ry   z>Callable[[httpx.Request], Coroutine[Any, Any, httpx.Response]]rW   rY   r\   )
r_   r`   ra   rb   r   DEFAULT_RETRYr   ru   rt   r|   re   r   r   rg   rg      sS    +1SzZ]^M+8 OC)[")[ \)[ 
	)[V/r   rg   )rb   
__future__r   r   email.utilsr1   rD   r.   r7   typingr   r   r   r   r   r	   loggingrM   r4   	getLoggerr_   rK   r   AsyncBaseTransportrg   re   r   r   <module>r      s^   
 #    	  B B   			8	${8 {8|?/%22 ?/r   