How to Mock a Circuit Breaker Reset Timeout in Python

This code implements a simple circuit breaker with a reset timeout test, simulating a flaky service to show half-open state transitions.

Medium Python 3.9+ Aug 9, 2026 Reliability & rate limiting 15 views 0 copies

Python code

57 lines
Python 3.9+
import time
import random


class CircuitBreaker:
    def __init__(self, failure_threshold=3, reset_timeout=5):
        self.failure_threshold = failure_threshold
        self.reset_timeout = reset_timeout
        self.failure_count = 0
        self.last_failure_time = None
        self.state = "CLOSED"  # CLOSED (normal), OPEN (tripped), HALF_OPEN (testing)

    def call(self, func):
        if self.state == "OPEN":
            if time.time() - self.last_failure_time >= self.reset_timeout:
                self.state = "HALF_OPEN"
                print("Circuit half-open: testing one request")
            else:
                print("Circuit OPEN: request rejected immediately")
                raise Exception("Circuit breaker is open")

        try:
            result = func()
            if self.state == "HALF_OPEN":
                self.state = "CLOSED"
                self.failure_count = 0
                print("Circuit closed after successful half-open test")
            else:
                self.failure_count = 0
            return result
        except Exception as e:
            self.failure_count += 1
            self.last_failure_time = time.time()
            if self.failure_count >= self.failure_threshold:
                self.state = "OPEN"
                print(f"Circuit OPEN after {self.failure_count} failures")
            raise e


# Simulated flaky service
def flaky_service():
    if random.random() < 0.6:
        raise ConnectionError("Service unavailable")
    return "Success"


if __name__ == "__main__":
    breaker = CircuitBreaker()
    for attempt in range(10):
        try:
            result = breaker.call(flaky_service)
            print(f"Attempt {attempt + 1}: {result}")
        except Exception as e:
            print(f"Attempt {attempt + 1}: FAILED ({e})")
        time.sleep(1.5)

    print(f"Final state: {breaker.state}")

Output

stdout
Circuit OPEN after 3 failures
Attempt 1: FAILED (Service unavailable)
Attempt 2: FAILED (Service unavailable)
Attempt 3: FAILED (Service unavailable)
Circuit OPEN: request rejected immediately
Attempt 4: FAILED (Circuit breaker is open)
Attempt 5: FAILED (Circuit breaker is open)
Circuit half-open: testing one request
Attempt 6: FAILED (Service unavailable)
Circuit OPEN after 4 failures
Attempt 7: FAILED (Service unavailable)
Circuit OPEN: request rejected immediately
Attempt 8: FAILED (Circuit breaker is open)
Circuit half-open: testing one request
Attempt 9: Success
Circuit closed after successful half-open test
Attempt 10: Success
Final state: CLOSED

How it works

The circuit breaker tracks consecutive failures and trips to OPEN when the threshold is reached. After reset_timeout seconds, it enters HALF_OPEN and lets one test request through. If that request succeeds, the circuit resets to CLOSED; if it fails, it returns to OPEN. The mock uses random failures to simulate a flaky service and time.sleep to control the reset timeout.

Common mistakes

  • Forgetting to update last_failure_time when a single request fails, causing open state to never reset
  • Resetting failure_count on success even when circuit is not half-open, masking repeated failures
  • Not handling exceptions in the half-open state correctly, leading to premature closing

Variations

  1. Use the 'pybreaker' library for a production-grade circuit breaker with more features
  2. Implement the reset timeout check using a background thread or async timer instead of blocking

Real-world use cases

  • Wrapping calls to an unreliable third-party API to prevent cascading failures in a microservice
  • Protecting a database connection during peak load when the database may become temporarily unavailable
  • Avoiding repeated retries to a downed backend service in a job scheduler, reducing load and wait time

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Reliability & rate limiting

Related tutorials and quizzes for this topic.