65 lines
2.0 KiB
Python
65 lines
2.0 KiB
Python
"""熔断器实现"""
|
|
import time
|
|
from typing import Callable, Any
|
|
from .state import CircuitState
|
|
|
|
|
|
class CircuitBreaker:
|
|
"""熔断器"""
|
|
|
|
def __init__(self, failure_threshold: int = 3, recovery_timeout: int = 60, half_open_requests: int = 1):
|
|
self.failure_threshold = failure_threshold
|
|
self.recovery_timeout = recovery_timeout
|
|
self.half_open_requests = half_open_requests
|
|
|
|
self.state = CircuitState.CLOSED
|
|
self.failure_count = 0
|
|
self.success_count = 0
|
|
self.last_failure_time = 0
|
|
self.half_open_calls = 0
|
|
|
|
def call(self, func: Callable, *args, **kwargs) -> Any:
|
|
"""执行调用"""
|
|
if self.state == CircuitState.OPEN:
|
|
if time.time() - self.last_failure_time >= self.recovery_timeout:
|
|
self.state = CircuitState.HALF_OPEN
|
|
self.half_open_calls = 0
|
|
else:
|
|
raise Exception("熔断器已打开,调用被拒绝")
|
|
|
|
try:
|
|
result = func(*args, **kwargs)
|
|
self._on_success()
|
|
return result
|
|
except Exception as e:
|
|
self._on_failure()
|
|
raise
|
|
|
|
def _on_success(self):
|
|
"""成功回调"""
|
|
self.failure_count = 0
|
|
if self.state == CircuitState.HALF_OPEN:
|
|
self.half_open_calls += 1
|
|
if self.half_open_calls >= self.half_open_requests:
|
|
self.state = CircuitState.CLOSED
|
|
self.half_open_calls = 0
|
|
|
|
def _on_failure(self):
|
|
"""失败回调"""
|
|
self.failure_count += 1
|
|
self.last_failure_time = time.time()
|
|
|
|
if self.state == CircuitState.HALF_OPEN:
|
|
self.state = CircuitState.OPEN
|
|
elif self.failure_count >= self.failure_threshold:
|
|
self.state = CircuitState.OPEN
|
|
|
|
def reset(self):
|
|
"""重置熔断器"""
|
|
self.state = CircuitState.CLOSED
|
|
self.failure_count = 0
|
|
self.half_open_calls = 0
|
|
|
|
def get_state(self) -> str:
|
|
return self.state
|