§
    ¨„›j*  ã                  ót   — d dl mZ d dlZd dlZd dlmZ d dlmZ  ej        d¦  «        Z	 G d„ d¦  «        Z
dS )é    )ÚannotationsN)ÚAny)ÚAiProviderTypezdscons.ai.circuit_breakerc                  ó8   — e Zd ZdZ	 	 ddd
„Zdd„Zdd„Zdd„ZdS )ÚProviderCircuitBreakerzZEnterprise Circuit Breaker to isolate failing AI providers and prevent cascading timeouts.é   ç      N@Úfailure_thresholdÚintÚrecovery_time_secondsÚfloatÚreturnÚNonec                ó¦   — || _         || _        d„ t          D ¦   «         | _        d„ t          D ¦   «         | _        d„ t          D ¦   «         | _        d S )Nc                ó   — i | ]}|d “ŒS )r   © ©Ú.0Úps     ú@C:\Projects\DSCons\app\core\ai\infrastructure\circuit_breaker.pyú
<dictcomp>z3ProviderCircuitBreaker.__init__.<locals>.<dictcomp>   s'   € ð ;
ð ;
ð ;
ØˆAˆqð;
ð ;
ð ;
ó    c                ó   — i | ]}|d “ŒS )ç        r   r   s     r   r   z3ProviderCircuitBreaker.__init__.<locals>.<dictcomp>   s-   € ð @
ð @
ð @
ØˆAˆsð@
ð @
ð @
r   c                ó   — i | ]}|d “ŒS )Fr   r   s     r   r   z3ProviderCircuitBreaker.__init__.<locals>.<dictcomp>   s'   € ð :
ð :
ð :
ØˆAˆuð:
ð :
ð :
r   )Ú_failure_thresholdÚ_recovery_timer   Ú_failure_countsÚ_last_failure_timeÚ_circuit_open)Úselfr
   r   s      r   Ú__init__zProviderCircuitBreaker.__init__   s‚   € ð
 #4ˆÔØ3ˆÔð;
ð ;
Ý(ð;
ñ ;
ô ;
ˆÔð@
ð @
Ý*ð@
ñ @
ô @
ˆÔð:
ð :
Ý,ð:
ñ :
ô :
ˆÔÐÐr   Úproviderr   Úboolc                óú   — | j                              |d¦  «        sdS t          j        ¦   «         | j                             |d¦  «        z
  }|| j        k    r#t
                               d|j        |¦  «         dS dS )z9Determines if requests can be sent to the given provider.FTr   zD[CIRCUIT_BREAKER] Probing provider %s after %.1fs recovery cooldown.)r    ÚgetÚtimer   r   ÚloggerÚinfoÚvalue)r!   r#   Úelapseds      r   Úcan_attemptz"ProviderCircuitBreaker.can_attempt    s‚   € àÔ!×%Ò% h°Ñ6Ô6ð 	Ø�4õ ”)‘+”+ Ô 7× ;Ò ;¸HÀcÑ JÔ JÑJˆØ�dÔ)Ò)Ð)Ý�KŠKØVØ”Øñô ð ð
 �4àˆur   c                ó¤   — | j                              |d¦  «        r t                               d|j        ¦  «         d| j        |<   d| j         |<   dS )z4Records a successful operation, closing the circuit.Fz8[CIRCUIT_BREAKER] Provider %s recovered. Circuit CLOSED.r   N)r    r&   r(   r)   r*   r   )r!   r#   s     r   Úrecord_successz%ProviderCircuitBreaker.record_success1   sW   € àÔ×!Ò! (¨EÑ2Ô2ð 	dÝ�KŠKÐRÐT\ÔTbÑcÔcÐcØ)*ˆÔ˜XÑ&Ø',ˆÔ˜8Ñ$Ð$Ð$r   ÚerrorúException | strc                óx  ‡— t          j         ¦   «         }|| j        |<   | j                             |d¦  «        dz   }|| j        |<   t	          |¦  «        Št          ˆfd„dD ¦   «         ¦  «        }|| j        k    s|r<d| j        |<   t           	                    d|j
        |‰dd…         | j        ¦  «         dS dS )	zMRecords an error (503, 429, timeout) and trips circuit if threshold exceeded.r   é   c              3  ó    •K  — | ]}|‰v V — Œ	d S )Nr   )r   ÚcodeÚerr_msgs     €r   ú	<genexpr>z8ProviderCircuitBreaker.record_failure.<locals>.<genexpr>B   s8   øè è € ð 
ð 
Ø $ˆD�GˆOð
ð 
ð 
ð 
ð 
ð 
r   )Ú503Ú429ÚRESOURCE_EXHAUSTEDÚUNAVAILABLETzn[CIRCUIT_BREAKER] Tripped circuit OPEN for provider %s (Consecutive failures: %d, reason: %s). Cooldown: %.0fsNéx   )r'   r   r   r&   ÚstrÚanyr   r    r(   Úwarningr*   r   )r!   r#   r/   ÚnowÚcountÚis_hard_failurer5   s         @r   Úrecord_failurez%ProviderCircuitBreaker.record_failure8   sð   ø€ õ Œi‰kŒkˆØ,/ˆÔ Ñ)ØÔ$×(Ò(¨°1Ñ5Ô5¸Ñ9ˆØ).ˆÔ˜XÑ&å�e‘*”*ˆÝð 
ð 
ð 
ð 
Ø([ð
ñ 
ô 
ñ 
ô 
ˆð �DÔ+Ò+Ð+¨Ð+Ø+/ˆDÔ˜xÑ(Ý�NŠNð AØ”ØØ˜˜˜”ØÔ#ñô ð ð ð ð ,Ð+r   N)r   r	   )r
   r   r   r   r   r   )r#   r   r   r$   )r#   r   r   r   )r#   r   r/   r0   r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r"   r,   r.   rB   r   r   r   r   r      sw   € € € € € ØdÐdð "#Ø'+ð
ð 
ð 
ð 
ð 
ð"ð ð ð ð"-ð -ð -ð -ðð ð ð ð ð r   r   )Ú
__future__r   Úloggingr'   Útypingr   Úapp.core.ai.domain.modelsr   Ú	getLoggerr(   r   r   r   r   ú<module>rL      sœ   ðØ "Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø Ð Ð Ð Ð Ð à 4Ð 4Ð 4Ð 4Ð 4Ð 4à	ˆÔ	Ð6Ñ	7Ô	7€ðBð Bð Bð Bð Bñ Bô Bð Bð Bð Br   