Files
sentinel-home-ai/fam-edge/src/fam_edge/model_adapters/circuit_breaker.py

53 lines
1.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
熔断器 - 每个云端模型独立实例
状态机: CLOSED -> OPEN -> HALF_OPEN -> CLOSED/OPEN
- 连续 threshold 次失败 -> OPEN
- 冷却 cooldown 秒后 -> HALF_OPEN允许一次探测
- 探测成功 -> CLOSED探测失败 -> 重新 OPEN
"""
from collections import deque
import time
import threading
class CircuitBreaker:
def __init__(self, threshold: int = 5, cooldown: int = 900, enabled: bool = True):
self.enabled = enabled
if enabled:
self.failures = deque(maxlen=threshold)
else:
self.failures = None
self.threshold = threshold
self.cooldown = cooldown
self.state = 'CLOSED'
self.last_failure = None
self._lock = threading.Lock() # 状态转换加锁,防多线程竞争
def record_failure(self):
if not self.enabled:
return
with self._lock:
self.failures.append(time.time())
if len(self.failures) >= self.threshold:
self.state = 'OPEN'
self.last_failure = time.time()
def record_success(self):
if not self.enabled:
return
with self._lock:
self.failures.clear()
self.state = 'CLOSED'
def is_open(self):
if not self.enabled:
return False
with self._lock:
if self.state == 'OPEN' and self.last_failure and time.time() - self.last_failure > self.cooldown:
self.state = 'HALF_OPEN'
return self.state == 'OPEN'
def __repr__(self):
return f"CircuitBreaker(state={self.state}, enabled={self.enabled})"