circuit-breaker
Resilience pattern preventing cascade failures by failing fast when a service is unavailable
Source facts
- Repository
- ffsshhttiikk/opencode-agents-skills
- Last source activity
- February 28, 2026 at 22:54
- Detected SKILL.md language
- English
- Stars
- 3
- Forks
- 2
Install options
The review-first prompt is selected by default. You can switch to a direct command or download a local copy.
Review the source files
Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.
Showing SKILL.md
SKILL.md
Source instructions · Read-only preview- name
- Circuit Breaker
- description
- Resilience pattern preventing cascade failures by failing fast when a service is unavailable
- category
- software-development
# Circuit Breaker
## What I do
I provide a resilience pattern that prevents cascade failures in distributed systems. The circuit breaker monitors calls to external services and tracks failures. When failures exceed a threshold, the circuit "opens," immediately failing requests without calling the failing service. This allows the failing service time to recover while preventing resource exhaustion. After a cooldown period, the circuit allows test requests to determine if the service has recovered.
## When to use me
Use circuit breakers when your application depends on external services that might fail or become slow. They're essential in microservice architectures, when calling third-party APIs, or when database connections might time out. Circuit breakers protect against cascade failures and help systems degrade gracefully. Don't use them for internal operations that are always fast or when you always want to attempt the call.
## Core Concepts
- **Closed State**: Normal operation, requests pass through
- **Open State**: Failure threshold exceeded, requests fail fast
- **Half-Open State**: Testing if service has recovered
- **Failure Threshold**: Number or percentage of failures to trigger
- **Timeout**: Time before attempting recovery
- **Failure Count**: Tracking consecutive failures
- **Success Count**: Tracking successful calls in half-open state
- **Fallback**: Alternative behavior when circuit is open
- **State Transitions**: Rules for moving between states
- **Metrics**: Monitoring circuit state changes
## Code Examples
### Basic Circuit Breaker Implementation
```python
from abc import ABC, abstractmethod
from dataclasses import dataclass
from datetime import datetime, timedelta
from enum import Enum
from typing import Callable, TypeVar, Generic
from uuid import uuid4
import time
class CircuitState(Enum):
CLOSED = "closed"
OPEN = "open"
HALF_OPEN = "half_open"
T = TypeVar("T")
@dataclass
class CircuitBreakerConfig:
failure_threshold: int = 5
success_threshold: int = 3
timeout_seconds: float = 60.0
half_open_max_calls: int = 3
@dataclass
class CircuitBreakerMetrics:
state: CircuitState
failure_count: int = 0
success_count: int = 0
total_calls: int = 0
last_failure_time: datetime | None = None
last_state_change: datetime = datetime.utcnow()
class CircuitBreaker:
def __init__(self, name: str, config: CircuitBreakerConfig = None):
self._name = name
self._config = config or CircuitBreakerConfig()
self._state = CircuitState.CLOSED
self._failure_count = 0
self._success_count = 0
self._last_failure_time: datetime | None = None
self._last_state_change = datetime.utcnow()
self._half_open_calls = 0
@property
def name(self) -> str:
return self._name
@property
def state(self) -> CircuitState:
self._check_state_transition()
return self._state
@property
def metrics(self) -> CircuitBreakerMetrics:
return CircuitBreakerMetrics(
state=self.state,
failure_count=self._failure_count,
success_count=self._success_count,
total_calls=self._failure_count + self._success_count,
last_failure_time=self._last_failure_time,
last_state_change=self._last_state_change
)
def call(self, func: Callable[..., T], *args, **kwargs) -> T:
if self.state == CircuitState.OPEN:
raise CircuitOpenError(
f"Circuit {self._name} is open. Service unavailable."
)
try:
result = func(*args, **kwargs)
self._on_success()
return result
except Exception as e:
self._on_failure()
raise
def _on_success(self) -> None:
if self._state == CircuitState.HALF_OPEN:
self._success_count += 1
self._half_open_calls += 1
if self._success_count >= self._config.success_threshold:
self._transition_to(CircuitState.CLOSED)
elif self._state == CircuitState.CLOSED:
self._failure_count = 0
def _on_failure(self) -> None:
self._failure_count += 1
self._last_failure_time = datetime.utcnow()
if self._state == CircuitState.HALF_OPEN:
self._transition_to(CircuitState.OPEN)
elif (
self._state == CircuitState.CLOSED and
self._failure_count >= self._config.failure_threshold
):
self._transition_to(CircuitState.OPEN)
def _check_state_transition(self) -> None:
if self._state == CircuitState.OPEN:
elapsed = datetime.utcnow() - self._last_state_change
if elapsed.total_seconds() >= self._config.timeout_seconds:
self._transition_to(CircuitState.HALF_OPEN)
def _transition_to(self, new_state: CircuitState) -> None:
old_state = self._state
self._state = new_state
self._last_state_change = datetime.utcnow()
if new_state == CircuitState.CLOSED:
self._failure_count = 0
self._success_count = 0
elif new_state == CircuitState.HALF_OPEN:
self._success_count = 0
self._half_open_calls = 0
print(f"Circuit {self._name}: {old_state} -> {new_state}")
class CircuitOpenError(Exception):
pass
class CircuitBreakerOpenError(Exception):
def __init__(self, circuit_name: str):
self.circuit_name = circuit_name
super().__init__(f"Circuit breaker '{circuit_name}' is open")
```
### Decorator-Based Circuit Breaker
```python
from functools import wraps
from typing import Callable, TypeVar, Generic
F = TypeVar("F", bound=Callable)
class CircuitBreakerDecorator:
def __init__(self, circuit: CircuitBreaker):
self._circuit = circuit
def __call__(self, func: F) -> F:
@wraps(func)
def wrapper(*args, **kwargs):
return self._circuit.call(func, *args, **kwargs)
return wrapper
def circuit_breaker(
name: str,
failure_threshold: int = 5,
timeout_seconds: float = 60
):
circuit = CircuitBreaker(
name=name,
config=CircuitBreakerConfig(
failure_threshold=failure_threshold,
timeout_seconds=timeout_seconds
)
)
decorator = CircuitBreakerDecorator(circuit)
def actual_decorator(func: F) -> F:
return decorator(func)
return actual_decorator
@circuit_breaker(name="payment-service", failure_threshold=3)
def process_payment(order_id: str, amount: float) -> dict:
print(f"Processing payment for order {order_id}")
if amount < 0:
raise ValueError("Invalid amount")
return {"order_id": order_id, "status": "paid", "amount": amount}
@circuit_breaker(name="user-service", failure_threshold=5)
def get_user(user_id: str) -> dict:
print(f"Fetching user {user_id}")
return {"user_id": user_id, "name": "John Doe"}
for i in range(10):
try:
result = process_payment(f"order-{i}", 100.0)
print(f"Success: {result}")
except CircuitOpenError as e:
print(f"Circuit open: {e}")
except Exception as e:
print(f"Error: {e}")
```
### Circuit Breaker with Fallback
```python
from abc import ABC, abstractmethod
from typing import Callable, Optional, Generic
class FallbackHandler(ABC):
@abstractmethod
def get_fallback(self, circuit_name: str, error: Exception) -> object:
pass
class CircuitBreakerWithFallback(CircuitBreaker):
def __init__(
self,
name: str,
config: CircuitBreakerConfig = None,
fallback_handler: FallbackHandler | None = None
):
super().__init__(name, config)
self._fallback_handler = fallback_handler
def call(
self,
func: Callable[..., T],
*args,
fallback: Optional[Callable[..., T]] = None,
**kwargs
) -> T:
try:
return super().call(func, *args, **kwargs)
except CircuitOpenError:
if fallback:
return fallback()
if self._fallback_handler:
return self._fallback_handler.get_fallback(self._name, CircuitOpenError(""))
raise
class DefaultFallbackHandler(FallbackHandler):
def __init__(self):
self._fallback_results = {}
def set_fallback_result(self, circuit_name: str, result: object) -> None:
self._fallback_results[circuit_name] = result
def get_fallback(self, circuit_name: str, error: Exception) -> object:
return self._fallback_results.get(circuit_name, {"status": "degraded"})
class PaymentServiceWithCircuitBreaker:
def __init__(self, fallback_handler: FallbackHandler):
self._circuit = CircuitBreakerWithFallback(
name="payment-service",
fallback_handler=fallback_handler
)
def process_payment(self, order_id: str, amount: float) -> dict:
def primary_payment():
return self._actual_payment(order_id, amount)
def fallback_payment():
return {"order_id": order_id, "status": "pending", "source": "fallback"}
return self._circuit.call(
primary_payment,
fallback=fallback_payment
)
def _actual_payment(self, order_id: str, amount: float) -> dict:
if amount > 10000:
raise ValueError("Amount exceeds limit")
return {"order_id": order_id, "status": "paid", "amount": amount}
```
### Multi-Circuit Breaker Manager
```python
from dataclasses import dataclass
from datetime import datetime
from typing import dict
@dataclass
class CircuitSummary:
name: str
state: CircuitState
failure_count: int
success_count: int
last_state_change: datetime
class CircuitManager:
def __init__(self):
self._circuits: dict[str, CircuitBreaker] = {}
def get_circuit(self, name: str, config: CircuitBreakerConfig = None) -> CircuitBreaker:
if name not in self._circuits:
self._circuits[name] = CircuitBreaker(name, config)
return self._circuits[name]
def remove_circuit(self, name: str) -> None:
if name in self._circuits:
del self._circuits[name]
def get_all_states(self) -> list[CircuitSummary]:
return [
CircuitSummary(
name=name,
state=circuit.state,
failure_count=circuit.metrics.failure_count,
success_count=circuit.metrics.success_count,
last_state_change=circuit.metrics.last_state_change
)
for name, circuit in self._circuits.items()
]
def reset_all(self) -> None:
for circuit in self._circuits.values():
circuit._transition_to(CircuitState.CLOSED)
class CircuitBreakerContext:
def __init__(self, manager: CircuitManager):
self._manager = manager
def __getitem__(self, name: str) -> CircuitBreaker:
return self._manager.get_circuit(name)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
pass
circuit_manager = CircuitManager()
circuits = CircuitBreakerContext(circuit_manager)
circuits["payment"].call(process_payment, "order-1", 100)
circuits["user"].call(get_user, "user-1")
```
### Async Circuit Breaker
```python
import asyncio
from typing import Callable, Awaitable
class AsyncCircuitBreaker:
def __init__(self, name: str, config: CircuitBreakerConfig = None):
self._name = name
self._config = config or CircuitBreakerConfig()
self._state = CircuitState.CLOSED
self._failure_count = 0
self._success_count = 0
self._last_failure_time: datetime | None = None
self._last_state_change = datetime.utcnow()
self._lock = asyncio.Lock()
@property
def state(self) -> CircuitState:
return self._state
async def call(
self,
func: Callable[..., Awaitable[T]],
*args,
**kwargs
) -> T:
async with self._lock:
if self._state == CircuitState.OPEN:
if self._should_attempt_reset():
self._state = CircuitState.HALF_OPEN
else:
raise CircuitOpenError(f"Circuit {self._name} is open")
try:
result = await func(*args, **kwargs)
await self._on_success()
return result
except Exception as e:
await self._on_failure()
raise
async def _should_attempt_reset(self) -> bool:
elapsed = datetime.utcnow() - self._last_state_change
return elapsed.total_seconds() >= self._config.timeout_seconds
async def _on_success(self) -> None:
async with self._lock:
if self._state == CircuitState.HALF_OPEN:
self._success_count += 1
if self._success_count >= self._config.success_threshold:
self._transition_to(CircuitState.CLOSED)
elif self._state == CircuitState.CLOSED:
self._failure_count = 0
async def _on_failure(self) -> None:
async with self._lock:
self._failure_count += 1
self._last_failure_time = datetime.utcnow()
View on GitHubThis SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub