o
    Zzj–  ã                   @   s¶   d Z ddlZddlZddlmZmZ ddlmZ ddlm	Z	m
Z
mZmZ eeƒZdddddœded	ef d
eegdf dB dededejdB deg ef dB dededdfdd„ZdS )a  This module contains a network retry loop implementation.
Its specifically tailored to handling the Telegram API and its errors.

.. versionadded:: 21.11

Hint:
    It was originally part of the `Updater` class, but as part of #4657 it was extracted into its
    own module to be used by other parts of the library.

Warning:
    Contents of this module are intended to be used internally by the library and *not* by the
    user. Changes to this module are not considered breaking changes and may not be documented in
    the changelog.
é    N)ÚCallableÚ	Coroutine)Ú
get_logger)ÚInvalidTokenÚ
RetryAfterÚTelegramErrorÚTimedOutF)Ú	on_err_cbÚ
stop_eventÚ
is_runningÚrepeat_on_successÚ	action_cb.r	   ÚdescriptionÚintervalr
   r   Úmax_retriesr   Úreturnc              
   ƒ   sä  �|rˆdkrt dƒ‚d|› d�‰|pdd„ }ddtd	td
tf‡‡fdd„}	d‡ ‡‡fdd„}
t dˆ¡ |}d}|ƒ rðzŸz|
ƒ I dH  |sTt dˆ¡ W W |d7 }dS W n~ ty~ } zd}||j ¡  }|› d|› d�}|	||ƒrt‚ W Y d}~n\d}~w t	y� } zd}d|› d�}|	||ƒr“‚ W Y d}~n=d}~w t
yª   t dˆ¡ ‚  tyÓ } z|r·||ƒ |	|ƒr¼‚ |dkrÂdntdd| ƒ}W Y d}~nd}~ww |}W |d7 }n|d7 }w |rët |¡I dH  |ƒ s<dS dS )aø  Perform a loop calling `action_cb`, retrying after network errors.

    Stop condition for loop in case of ``max_retries < 0``:
        * `is_running()` evaluates :obj:`False`
        * `stop_event` is set.
        * calling `action_cb` succeeds and `repeat_on_success` is :obj:`False`.

    Additional stop condition for loop in case of `max_retries >= 0``:
        * a call to `action_cb` succeeds
        * or `max_retries` is reached.

    Args:
        action_cb (:term:`coroutine function`): Network oriented callback function to call.
        on_err_cb (:obj:`callable`): Optional. Callback to call when TelegramError is caught.
            Receives the exception object as a parameter.

            Hint:
                Only required if you want to handle the error in a special way. Logging about
                the error is already handled by the loop.

            Important:
                Must not raise exceptions! If it does, the loop will be aborted.
        description (:obj:`str`): Description text to use for logs and exception raised.
        interval (:obj:`float` | :obj:`int`): Interval to sleep between each call to
            `action_cb`.
        stop_event (:class:`asyncio.Event` | :obj:`None`): Event to wait on for stopping the
            loop. Setting the event will make the loop exit even if `action_cb` is currently
            running. Defaults to :obj:`None`.
        is_running (:obj:`callable`): Function to check if the loop should continue running.
            Must return a boolean value. Defaults to `lambda: True`.
        max_retries (:obj:`int`): Maximum number of retries before stopping the loop.

            * < 0: Retry indefinitely.
            * 0: No retries.
            * > 0: Number of retries.

        repeat_on_success (:obj:`bool`): Whether to repeat the action after a successful call.
            Defaults to :obj:`False`.

    Raises:
        ValueError: When passing `repeat_on_success=True` and `max_retries >= 0`. This case is
            currently not supported.

    r   z7Cannot use repeat_on_success=True with max_retries >= 0zNetwork Retry Loop (z):c                   S   s   dS )NT© r   r   r   úZ/var/www/kodo/tsheker/venv/lib/python3.10/site-packages/telegram/ext/_utils/networkloop.pyÚ<lambda>h   s    z$network_retry_loop.<locals>.<lambda>Ú Úcurrent_retriesÚexception_infor   c                    sN   |r	ˆ › d|› �nˆ }ˆdk s| ˆk rt  d|| ˆ¡ dS t  d|| ˆ¡ dS )aL  Check if max retries reached and log accordingly.

        Args:
            current_retries: The current retry count.
            exception_info: Additional context about the exception (e.g., "Timed out: ...").

        Returns:
            bool: True if max retries reached (should abort), False otherwise (should retry).
        ú r   z(%s Failed run number %s of %s. Retrying.Fz(%s Failed run number %s of %s. Aborting.T)Ú_LOGGERÚdebugÚ	exception)r   r   Úprefix_with_info)Ú
log_prefixr   r   r   Úcheck_max_retries_and_logj   s    
üüz5network_retry_loop.<locals>.check_max_retries_and_logNc                  “   s°   �ˆsˆ ƒ I d H  d S t  ˆ ƒ ¡} t  ˆ ¡ ¡}t j| |ft jd�I d H \}}t t j¡� |D ]}| ¡  q0W d   ƒ n1 sAw   Y  ||v rRt 	dˆ¡ d S |  
¡  d S )N)Úreturn_whenz%s Cancelled)ÚasyncioÚcreate_taskÚwaitÚFIRST_COMPLETEDÚ
contextlibÚsuppressÚCancelledErrorÚcancelr   r   Úresult)Úaction_cb_taskÚ	stop_taskÚdoneÚpendingÚtask)r   r   r
   r   r   Ú	do_action†   s$   €
ÿ
ÿÿz%network_retry_loop.<locals>.do_actionz%s Startingz#%s Action succeeded. Stopping loop.é   g      à?z	. Adding z seconds to the specified time.zTimed out: Ú.z&%s Invalid token. Aborting retry loop.é   g      ø?)r   )r   N)Ú
ValueErrorÚintÚstrÚboolr   r   r   Ú_retry_afterÚtotal_secondsr   r   r   r   Úminr    Úsleep)r   r	   r   r   r
   r   r   r   Úeffective_is_runningr   r.   Úcur_intervalÚretriesÚexcÚ
slack_timer   ÚtoeÚtelegram_excr   )r   r   r   r
   r   Únetwork_retry_loop,   sd   €7!Ý
ÿ€
ÿ€&€ø
€×rA   )Ú__doc__r    r$   Úcollections.abcr   r   Útelegram._utils.loggingr   Útelegram.errorr   r   r   r   Ú__name__r   r4   ÚfloatÚEventr5   r3   rA   r   r   r   r   Ú<module>   s<   ÷
þýüûúùø	÷
ö