
    Ii?	                    R    d Z ddlmZ ddlZddlmZ  G d de      Z G d d      Zy)	u8   engine_v2/circuit_breaker.py — Circuit Breaker 패턴.    )annotationsN)Enumc                      e Zd ZdZdZdZy)CBStateCLOSEDOPEN	HALF_OPENN)__name__
__module____qualname__r   r   r	        H/home/jay/workspace/services/multimodel-bot/engine_v2/circuit_breaker.pyr   r   	   s    FDIr   r   c                  h    e Zd ZdZ	 	 	 d
	 	 	 	 	 	 	 ddZedd       ZddZddZddZ	ddZ
ddZy	)CircuitBreakeru   Circuit Breaker.

    확정 수치:
        fail_threshold: 3 (fluke 2회 허용)
        recovery_sec: 120 (600초 타임아웃의 1/5)
        half_max_calls: 1 (복구 확인 최소)
    c                    || _         || _        || _        t        j                  | _        d| _        d| _        d| _        y )Nr           )	_fail_threshold_recovery_sec_half_max_callsr   r   _state_fail_count_last_fail_time_half_open_calls)selffail_thresholdrecovery_sechalf_max_callss       r   __init__zCircuitBreaker.__init__   s?      .)-nn&) !r   c                :    | j                          | j                  S )N)_check_recoveryr   r   s    r   statezCircuitBreaker.state&   s    {{r   c                    | j                          | j                  t        j                  k(  ry| j                  t        j                  k(  r0| j
                  | j                  k  r| xj
                  dz  c_        yyy)u   요청 허용 여부.T   F)r!   r   r   r   r	   r   r   r"   s    r   allow_requestzCircuitBreaker.allow_request+   sa    ;;'..(;;'+++$$t';';;%%*%r   c                    | j                   t        j                  k(  r$t        j                  | _         d| _        d| _        yy)u   성공 기록.r   N)r   r   r	   r   r   r   r"   s    r   record_successzCircuitBreaker.record_success7   s4    ;;'+++!..DK D$%D! ,r   c                    | xj                   dz  c_         t        j                         | _        | j                   | j                  k\  rt
        j                  | _        yy)u   실패 기록.r%   N)r   time	monotonicr   r   r   r   r   r"   s    r   record_failurezCircuitBreaker.record_failure>   sF    A#~~/t333!,,DK 4r   c                    | j                   t        j                  k(  rNt        j                         | j
                  z
  }|| j                  k\  rt        j                  | _         d| _        yyy)u!   OPEN → HALF_OPEN 전환 체크.r   N)	r   r   r   r*   r+   r   r   r	   r   )r   elapseds     r   r!   zCircuitBreaker._check_recoveryE   sV    ;;',,&nn&)=)==G$,,,%//()% - 'r   c                X    t         j                  | _        d| _        d| _        d| _        y)u   상태 초기화.r   r   N)r   r   r   r   r   r   r"   s    r   resetzCircuitBreaker.resetM   s%    nn" !r   N)   x   r%   )r   intr   r3   r   r3   returnNone)r4   r   )r4   bool)r4   r5   )r
   r   r   __doc__r   propertyr#   r&   r(   r,   r!   r0   r   r   r   r   r      sj      	"" " 	"
 
"  
&'*"r   r   )r7   
__future__r   r*   enumr   r   r   r   r   r   <module>r;      s)    > "  d C" C"r   