PyBreaker

1.4.1 · active · verified Mon Apr 06

PyBreaker is a Python implementation of the Circuit Breaker pattern, a resilience mechanism described in Michael T. Nygard's book 'Release It!'. It prevents cascading failures in distributed systems by detecting unhealthy services and temporarily stopping requests to them. The library provides configurable failure thresholds, reset timeouts, and optional Redis backing for state management. It is actively maintained, with the current version being 1.4.1, and receives regular updates.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to apply a circuit breaker to protect calls to an unreliable external service using `pybreaker.CircuitBreaker` as a decorator. It simulates service failures and shows how the circuit transitions between `CLOSED`, `OPEN`, and `HALF_OPEN` states, with appropriate error handling and a fallback mechanism.

import pybreaker
import requests

# Simulate a flaky external service
_service_up = True

def external_service_call():
    global _service_up
    if _service_up:
        print("Calling external service...")
        # Simulate a network error or service unavailability
        if requests.get("http://localhost:9999/health", timeout=0.1).status_code != 200:
            raise requests.exceptions.ConnectionError("Service not reachable")
        return "Service data"
    else:
        print("Service is intentionally down (simulated).")
        raise requests.exceptions.ConnectionError("Service is down")

# Create a circuit breaker instance
# Opens after 3 failures within 60 seconds
# Stays open for 10 seconds before trying again (half-open)
my_breaker = pybreaker.CircuitBreaker(
    fail_max=3,
    reset_timeout=10,
    exclude=[requests.exceptions.HTTPError] # Exclude HTTP errors that are not system failures
)

@my_breaker
def protected_call():
    return external_service_call()

print("--- Starting Circuit Breaker Demo ---")

for i in range(10):
    print(f"\nAttempt {i+1}:")
    try:
        result = protected_call()
        print(f"Success: {result}")
        _service_up = True # Reset service state on success to show circuit closing
    except pybreaker.CircuitBreakerError:
        print("Circuit OPEN! Falling back to cached data or default.")
        _service_up = False # Keep service down if breaker opened
    except requests.exceptions.ConnectionError as e:
        print(f"Connection error: {e}. Circuit state: {my_breaker.current_state}")
        # Simulate service coming back up after a few failures
        if i == 5: # Make service available after 5 attempts
            _service_up = True
    except Exception as e:
        print(f"Unexpected error: {e}")

# A real application would not typically control _service_up like this in quickstart,
# but it illustrates the breaker's behavior.

view raw JSON →