
    :j7                        d Z ddlZddlZddlZddlZddlmZmZ ddlm	Z	m
Z
mZ ddlmZ  ed      Z G d d	      Z G d
 de      Z G d de      Z G d de      Z G d de      Z G d de      Zddddefdfdedededede
ee   df   defd Z	 	 	 	 	 d+d!e
ee   df   dededededefd"Zd#e	d$e	fd%Zd,d&ed$efd'Z	 	 	 	 	 d-ded(ededed)ef
d*Zy).aY  
Unified Retry Framework - Comprehensive Retry Logic and Strategies

This module provides a unified retry framework that combines:
- Strategy Pattern: Object-oriented retry policies for pipeline stages
- Decorator Pattern: Function decorators for automatic retry
- Core Algorithms: Shared retry logic with exponential backoff and jitter

Key Features:
- Multiple retry strategies (Fixed, Exponential, Jitter, None)
- Decorator support for sync/async functions
- Smart error classification and retry decisions
- Dynamic parameter extraction from function arguments
- Unified configuration and behavior
    N)ABCabstractmethod)CallableTupleType   )
get_loggerretryc                   `    e Zd ZdZededededefd       Ze	 ddede	de	d	e	d
ede	fd       Z
y)	RetryCorezFCore retry algorithms and utilities shared across all retry mechanismserrorattemptmax_retriesreturnc                     ||k\  ryt        | t        t        f      ryt        |       j	                         }d|v sd|v ryt        | t
        t        t        f      ryy)a'  Determine if an error should trigger a retry

        Args:
            error: Exception that occurred
            attempt: Current attempt number (0-based)
            max_retries: Maximum number of retries allowed

        Returns:
            bool: True if error should trigger retry
        FTz
rate limitztoo many requests)
isinstanceConnectionErrorTimeoutErrorstrlower
ValueError	TypeErrorKeyError)r   r   r   	error_strs       2/root/.openclaw/workspace/harvester/tools/retry.pyshould_retry_errorzRetryCore.should_retry_error'   sc     k! eo|<= J$$&	9$(;y(H ej)X>?    
base_delay
multiplier	max_delayjitterc                     ||| z  z  }t        ||      }|r+d}t        j                  | |      |z  }t        d||z         }|S )a  Calculate retry delay with exponential backoff and optional jitter

        Args:
            attempt: Current attempt number (0-based)
            base_delay: Base delay in seconds
            multiplier: Exponential multiplier
            max_delay: Maximum delay cap
            jitter: Whether to add random jitter

        Returns:
            float: Calculated delay in seconds
        皙?)minrandomuniformmax)r   r   r   r    r!   delayjitter_factorjitter_amounts           r   calculate_delayzRetryCore.calculate_delayE   sV    " j'12E9% M"NNM>=IEQMU]23Er   N)      ?       @      >@T)__name__
__module____qualname____doc__staticmethod	Exceptionintboolr   floatr+    r   r   r   r   $   s{    P) c  PT  : pt"';@SXim	 r   r   c                   H    e Zd ZdZedededefd       Zedede	fd       Z
y)RetryPolicyz&Abstract base class for retry policiesr   r   r   c                      y)zDetermine if task should be retried

        Args:
            attempt: Current attempt number (0-based)
            error: Exception that occurred

        Returns:
            bool: True if task should be retried
        Nr8   selfr   r   s      r   should_retryzRetryPolicy.should_retryj   s     	r   c                      y)zGet delay before next retry attempt

        Args:
            attempt: Current attempt number (0-based)

        Returns:
            float: Delay in seconds
        Nr8   r=   r   s     r   	get_delayzRetryPolicy.get_delayw   s     	r   N)r/   r0   r1   r2   r   r5   r4   r6   r>   r7   rA   r8   r   r   r:   r:   g   sN    0
C 
	 
d 
 
 	 	 	 	r   r:   c                   F    e Zd ZdZddedefdZdededefdZ	dedefd	Z
y
)
FixedRetryzFixed delay retry policyr   r(   c                      || _         || _        y N)r   r(   )r=   r   r(   s      r   __init__zFixedRetry.__init__   s    &
r   r   r   r   c                 D    t         j                  ||| j                        S )z'Check if should retry with fixed policyr   r   r   r<   s      r   r>   zFixedRetry.should_retry       ++E7D<L<LMMr   c                     | j                   S )zReturn fixed delay)r(   r@   s     r   rA   zFixedRetry.get_delay   s    zzr   N)   r,   r/   r0   r1   r2   r5   r7   rF   r4   r6   r>   rA   r8   r   r   rC   rC      sI    "C E NC N	 Nd N  r   rC   c            	       N    e Zd ZdZddedededefdZdeded	efd
Z	ded	efdZ
y)ExponentialBackoffz Exponential backoff retry policyr   r   r    r   c                 <    || _         || _        || _        || _        y rE   )r   r   r    r   )r=   r   r   r    r   s        r   rF   zExponentialBackoff.__init__   s    &$"$r   r   r   r   c                 D    t         j                  ||| j                        S )z.Check if should retry with exponential backoffrH   r<   s      r   r>   zExponentialBackoff.should_retry   rI   r   c                 r    t         j                  || j                  | j                  | j                  d      S )z#Calculate exponential backoff delayFr!   r   r+   r   r   r    r@   s     r   rA   zExponentialBackoff.get_delay   s.    (($//4??TXTbTbkp(qqr   N)rK   r,   r.   r-   rL   r8   r   r   rN   rN      s\    *%C % %QV %kp %NC N	 Nd Nr r rr   rN   c                   T     e Zd ZdZ	 	 	 	 	 ddededededef
 fdZded	efd
Z xZS )JitterBackoffz8Exponential backoff with jitter to avoid thundering herdr   r   r    r   r)   c                 8    t         |   ||||       || _        y rE   )superrF   r)   )r=   r   r   r    r   r)   	__class__s         r   rF   zJitterBackoff.__init__   s      	j)ZH*r   r   r   c                 r    t         j                  || j                  | j                  | j                  d      S )z/Calculate exponential backoff delay with jitterTrR   rS   r@   s     r   rA   zJitterBackoff.get_delay   s.    (($//4??TXTbTbko(ppr   )rK   r,   r.   r-   r#   )	r/   r0   r1   r2   r5   r7   rF   rA   __classcell__)rX   s   @r   rU   rU      sb    B "	+	+ 	+ 		+
 	+ 	+q q qr   rU   c                   4    e Zd ZdZdededefdZdedefdZ	y)NoRetryz"No retry policy - fail immediatelyr   r   r   c                      y)zNever retryFr8   r<   s      r   r>   zNoRetry.should_retry   s    r   c                      y)zNo delay neededg        r8   r@   s     r   rA   zNoRetry.get_delay   s    r   N)
r/   r0   r1   r2   r5   r4   r6   r>   r7   rA   r8   r   r   r\   r\      s2    ,C 	 d   r   r\   rK   r,   r-   Tr.   max_attemptsr(   backoff_factorr!   
exceptions.r    c                 @     dt         dt         f fd}|S )a  Decorator for automatic retry with exponential backoff using unified core

    Args:
        max_attempts: Maximum number of retry attempts
        delay: Initial delay between retries in seconds
        backoff_factor: Multiplier for delay after each failure
        jitter: Whether to add random jitter to delay
        exceptions: Tuple of exceptions to catch and retry
        max_delay: Maximum delay cap in seconds

    Returns:
        Decorated function with retry logic
    funcr   c                      t        j                          fd       }t        j                          fd       }t        j                         r|S |S )Nc                  X   d }t              D ]  }	  	| i |c S  |# $ r}|}|dz
  k  rUt        j                  |
      }t        j	                  d|dz    d d| d|dd	       t        j                  |       nt        j                  d d	|        Y d }~d }~ww xY w
Nr   zAttempt /z	 failed: z. Retrying in z.2fzs...zAll z attempts failed. Last error: )ranger   r+   loggerwarningtimesleepr   argskwargslast_exceptionr   eactual_delayr`   r(   ra   rc   r!   r_   r    s         r   sync_wrapperz3with_retry.<locals>.decorator.<locals>.sync_wrapper   s    !N . ]]000]" !  " ]%&N!11'0'@'@%Q_ajlr's&w{m1\N)A3N`amnq`rrvw 

<0tL>9WXYWZ%[\]s    B)A:B$$B)c                    K   d }t              D ]  }	  	| i | d {   c S  |7 	# $ r}|}|dz
  k  r^t        j                  |
      }t        j	                  d|dz    d d| d|dd	       t        j                  |       d {  7   nt        j                  d d	|        Y d }~d }~ww xY wwrf   )rh   r   r+   ri   rj   asynciorl   r   rm   s         r   async_wrapperz4with_retry.<locals>.decorator.<locals>.async_wrapper   s     !N . ]]!%t!6v!666]" !  7! ]%&N!11'0'@'@%Q_ajlr's&w{m1\N)A3N`amnq`rrvw &mmL999tL>9WXYWZ%[\]sC   C,*,C,B>A!B9B!B94C9B>>C)	functoolswrapsru   iscoroutinefunction)	rc   rs   rv   r`   r(   ra   r!   r_   r    s	   `  r   	decoratorzwith_retry.<locals>.decorator   sa    			! 	! 
	!, 
		! 	! 
	!. &&t,  r   )r   )r_   r(   r`   r!   ra   r    rz   s   `````` r   
with_retryr{      s$    ,3  3 X 3  3 j r   exception_typesc                 $    t        ||||| |      S )a  Retry decorator for specific exception types

    Args:
        exception_types: Tuple of exception types to retry on
        max_attempts: Maximum number of retry attempts
        delay: Initial delay between retries in seconds
        backoff_factor: Multiplier for delay after each failure
        jitter: Whether to add random jitter to delay
        max_delay: Maximum delay cap in seconds

    Returns:
        Decorated function with retry logic
    r_   r(   r`   r!   ra   r    )r{   )r|   r_   r(   r`   r!   r    s         r   retry_on_exceptionr     s#    * !%" r   rc   r   c                 B     t        j                          fd       }|S )a  Smart network retry decorator that extracts retry configuration from function parameters

    This decorator automatically extracts 'retries' and 'interval' parameters from the decorated
    function's arguments and applies dynamic retry logic accordingly. If these parameters are not
    provided, it falls back to sensible defaults.

    Args:
        func: Function to be decorated

    Returns:
        Decorated function with dynamic retry capability

    Example:
        @network_retry
        def http_get(url, retries=3, interval=1.0):
            # Function implementation
            pass

        # Uses custom retry configuration
        http_get("http://example.com", retries=5, interval=2.0)

        # Uses default configuration
        http_get("http://example.com")
    c                  |   |j                  dd      }|j                  dd      }	 |t        dt        |            nd}|t        dt        |            nd}t        ||d	d
t        t        fd      }  |      | i |S # t        t
        f$ r* d}d}t        j                  dj                   d       Y aw xY w)NretriesrK   intervalr,   r   r#   zInvalid retry parameters for z, using defaultsr-   Tr.   r~   )getr'   r5   r7   r   r   ri   rj   r/   r{   r   r   )rn   ro   r   r   retry_decoratorrc   s        r   wrapperznetwork_retry.<locals>.wrapperQ  s     **Y*::j#.	\.5.Ac!S\*qG4<4Hs3h0cH % '6
 %t$d5f55# I& 	\GHNN:4==/IYZ[		\s   2B 6B;:B;)rw   rx   )rc   r   s   ` r   network_retryr   7  s'    4 __T6 68 Nr   policy_typec                     | j                         } | dk(  rt        di |S | dk(  rt        di |S | dk(  rt        di |S | dk(  r
t	               S t
        j                  d|  d       t        di |S )zFactory function to create retry policies

    Args:
        policy_type: Type of policy ('fixed', 'exponential', 'jitter', 'none')
        **kwargs: Policy-specific parameters

    Returns:
        RetryPolicy: Configured retry policy instance
    fixedexponentialr!   nonezUnknown retry policy type: z, using exponential backoffr8   )r   rC   rN   rU   r\   ri   rj   )r   ro   s     r   create_retry_policyr   v  s     ##%Kg#F##		%!+F++		 &v&&		y4[MA\]^!+F++r   r   network_errors_onlyc                 P    |rt         t        f}nt        f}t        | |d|||      S )af  Smart retry decorator that uses intelligent error classification

    Args:
        max_attempts: Maximum retry attempts
        base_delay: Initial delay in seconds
        max_delay: Maximum delay cap
        jitter: Whether to add jitter
        network_errors_only: If True, only retry network-related errors

    Returns:
        Decorator function
    r-   r~   )r   r   r4   r{   )r_   r   r    r!   r   ra   s         r   smart_retryr     s7    & %|4
\
! r   )rK   r,   r-   Tr.   )r   )rK   r,   r.   TT)r2   ru   rw   r%   rk   abcr   r   typingr   r   r   ri   r	   r   r:   rC   rN   rU   r\   r4   r5   r7   r6   r{   r   r   r   r   r   r8   r   r   <module>r      s        # ( ( 	G	; ;F# :  r r$q& q&	k 	$ /8lKKK K 	K
 d9os*+K K` 4	?C/0  	
  >7 7X 7~,S ,{ ,4  $  	
 r   