
    ib                     J   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mZ  e ed            Zej                  j                  dd      ZdZd	Zd
ZdedefdZdededdfdZdededefdZefdededefdZdefdedededededefdZefdedefdZddZedk(  r e        yy)u  Circuit Breaker - hooks 자동 강제 시 과도한 에러 감지 및 halt.

상태 파일: /home/jay/workspace/.metrics/circuit_breaker_state.json

발동 조건:
- warning 누적 15회 → halt
- critical 누적 30회 → halt
- 동일 (tool, error_code, file_path) 3-tuple 연속 3회 → halt

CLI:
    python3 circuit_breaker.py check <file_path>
    python3 circuit_breaker.py record <severity> <file_path> <error_code>
    python3 circuit_breaker.py reset
    N)datetime	timedeltatimezone	   )hoursCIRCUIT_BREAKER_STATEz7/home/jay/workspace/.metrics/circuit_breaker_state.json         
state_pathreturnc           	         	 t        | dd      5 }t        j                  |      cddd       S # 1 sw Y   yxY w# t        t        j                  f$ r2 dt        j                  t              j                         ddg dddcY S w xY w)	u5   상태 파일 로드. 없으면 초기 상태 반환.rzutf-8)encodingN1.0r   Fschema_version
updated_atwarning_countcritical_countrecent_eventshaltedhalt_reason)	openjsonloadFileNotFoundErrorJSONDecodeErrorr   nowKST	isoformat)r   fs     F/home/jay/workspace/.worktrees/task-2116-dev1/hooks/circuit_breaker.py_load_stater$   #   s    
*cG4 	 99Q<	  	  	 t334 	
#",,s+557
 	
	
s$   ; /	; 8; ; ABBstatec                    t        j                  t              j                         | d<   t        j
                  j                  |      }t	        j                  |d       t        j                  d|dd      5 }t        j                  | |dd	       |j                  }d
d
d
       t	        j                  |       y
# 1 sw Y    xY w)u   atomic write로 상태 저장.r   T)exist_okwFz.tmp)modedirdeletesuffix   )indentensure_asciiN)r   r   r    r!   ospathdirnamemakedirstempfileNamedTemporaryFiler   dumpnamereplace)r%   r   dir_pathr"   tmp_paths        r#   _save_stater;   4   s    ",,s+557E,wwz*HKK4(		$	$#8ERX	Y ]^		%15966 JJx$ s   :&B??Cr   	new_eventc                     |j                  dd      |d   |d   f}d}t        | dd       D ]+  }|j                  dd      |d   |d   f|k(  r|dz  }' |d	k\  S  |d	k\  S )
uG   동일 (tool, error_code, file_path) 3-tuple이 연속 3회이면 True.toolWrite
error_code	file_pathr   N   r-   )getreversed)r   r<   keyconsecutiveevents        r#   _check_consecutive_haltrI   ?   s    ==)9\+BIkDZ
[CK-,- IIfg&l(;U;=OPTWW1K!
 !    rA   c                 @    t        |      }|j                  dd      ryy)u\   현재 상태에서 실행 허용 여부 확인. file_path는 CLI 인터페이스 호환용.r   Fhaltok)r$   rD   )rA   r   r%   s      r#   	cmd_checkrN   K   s     
#Eyy5!rJ   r?   severityr@   r>   c                    t        |      }|||| t        j                  t              j	                         d}| dk(  r|j                  dd      dz   |d<   n|j                  dd      dz   |d<   t        |j                  dg       |      rd|d	<   d
| d| d| d|d<   |j                  dd      t        k\  rd|d	<   d|d    dt         |d<   |j                  dd      t        k\  rd|d	<   d|d    dt         |d<   |j                  dg       }|j                  |       |dd |d<   t        ||       |j                  d	      rdS dS )u&   이벤트 기록 + halt 조건 검사.)r>   r@   rA   rO   	timestampcriticalr   r   rC   r   r   Tr   zconsecutive_3tuple: (z, )r   zwarning_threshold: z >= zcritical_threshold: iNrL   rM   )r$   r   r   r    r!   rD   rI   WARNING_THRESHOLDCRITICAL_THRESHOLDappendr;   )rO   rA   r@   r>   r   r%   r<   eventss           r#   
cmd_recordrX   S   s    
#E  \\#&002I :"')),<a"@1"D!&?A!>!Bo uyy"=yIh!6tfBzl"YKWXYm yy!$(99h!4U?5K4LDQbPcdmyy!1%);;h!5e<L6M5NdSeRfgm YY+F
MM)#DE]E/z"YYx(62d2rJ   c                 z    dt        j                  t              j                         ddg ddd}t	        ||        y)u   수동 리셋.r   r   FNr   rM   )r   r   r    r!   r;   )r   r%   s     r#   	cmd_resetrZ      sA      ll3'113E z"rJ   c                     t        t        j                        dk  r0t        dt        j                         t        j
                  d       t        j                  d   } | dk(  rt        t        j                        dk  r0t        dt        j                         t        j
                  d       t        t        j                  d         }|dk(  rt        j
                  d       t        j
                  d	       y | d
k(  rt        t        j                        dk  r0t        dt        j                         t        j
                  d       t        t        j                  d   t        j                  d   t        j                  d   t        t        j                        dkD  rt        j                  d   nd      }|dk(  rt        j
                  d       t        j
                  d	       y | dk(  r+t                t        d       t        j
                  d	       y t        d|  t        j                         t        j
                  d       y )Nr-   z8Usage: circuit_breaker.py <check|record|reset> [args...])filerC   checkr   z+Usage: circuit_breaker.py check <file_path>rL   r   record   zDUsage: circuit_breaker.py record <severity> <file_path> <error_code>   r?   )rO   rA   r@   r>   resetzCircuit breaker reset.zUnknown command: )	lensysargvprintstderrexitrN   rX   rZ   )commandresults     r#   mainrj      s{   
388}qHszzZhhqkG'sxx=1?cjjQHHQK388A;'VHHQK	H	sxx=1X_b_i_ijHHQKXXa[hhqkxx{ #CHH 1!w	
 VHHQK	G	&' 	!'+#**=rJ   __main__)r   N)__doc__r   r0   rc   r4   r   r   r   r    environrD   
STATE_PATHrT   rU   CONSECUTIVE_THRESHOLDstrdictr$   r;   listboolrI   rN   rX   rZ   rj   __name__ rJ   r#   <module>rv      s7    	 
  2 2yq!"ZZ^^=

    
C 
D 
"%t % % %	4 	D 	T 	 1;  # s   -3-3-3 -3 	-3
 -3 	-3` !+ # s %P zF rJ   