ruby 70 lines · 9 steps

How a circuit breaker guards failing calls

A thread-safe state machine that stops hammering a failing dependency and probes for recovery.

Explained by highlit
1class CircuitBreaker
2 class OpenCircuitError < StandardError; end
3 
4 def initialize(failure_threshold: 5, reset_timeout: 30, half_open_max: 1)
5 @failure_threshold = failure_threshold
6 @reset_timeout = reset_timeout
7 @half_open_max = half_open_max
8 @state = :closed
9 @failures = 0
10 @opened_at = nil
11 @half_open_calls = 0
12 @mutex = Mutex.new
13 end
14 
15 def call
16 @mutex.synchronize { transition_from_open if open? && reset_timeout_elapsed? }
17 
18 raise OpenCircuitError, "circuit is open" if reject_call?
19 
20 begin
21 result = yield
22 record_success
23 result
24 rescue StandardError => e
25 record_failure
26 raise e
27 end
28 end
29 
30 private
31 
32 def open?
33 @state == :open
34 end
35 
36 def reject_call?
37 @mutex.synchronize do
38 return true if open?
39 @half_open_calls += 1 if @state == :half_open
40 @state == :half_open && @half_open_calls > @half_open_max
41 end
42 end
43 
44 def reset_timeout_elapsed?
45 @opened_at && (Time.now - @opened_at) >= @reset_timeout
46 end
47 
48 def transition_from_open
49 @state = :half_open
50 @half_open_calls = 0
51 end
52 
53 def record_success
54 @mutex.synchronize do
55 @failures = 0
56 @state = :closed
57 @opened_at = nil
58 end
59 end
60 
61 def record_failure
62 @mutex.synchronize do
63 @failures += 1
64 if @state == :half_open || @failures >= @failure_threshold
65 @state = :open
66 @opened_at = Time.now
67 end
68 end
69 end
70end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A circuit breaker trades a fast failure for a slow one, protecting a struggling dependency from being overwhelmed.
  2. 2The half-open state acts as a controlled probe, letting a limited number of trial calls decide whether the circuit reopens or fully closes.
  3. 3Guarding every shared-state mutation with a mutex keeps the breaker correct when many threads call it at once.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How a circuit breaker guards failing calls — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code