Class: Fizzy::CircuitBreaker
- Inherits:
-
Object
- Object
- Fizzy::CircuitBreaker
- Defined in:
- lib/fizzy/circuit_breaker.rb
Overview
Circuit breaker pattern for fault tolerance.
Tracks consecutive failures and opens the circuit when the threshold is reached, preventing further requests until the recovery timeout expires.
States:
-
:closed – normal operation, requests flow through
-
:open – circuit tripped, requests fail immediately
-
:half_open – recovery probe, single request allowed through
Instance Method Summary collapse
-
#call { ... } ⇒ Object
Executes the block through the circuit breaker.
-
#initialize(threshold: 5, timeout: 30) ⇒ CircuitBreaker
constructor
A new instance of CircuitBreaker.
-
#reset ⇒ Object
Resets the circuit breaker to closed state.
-
#state ⇒ Symbol
Current circuit state (:closed, :open, :half_open).
Constructor Details
#initialize(threshold: 5, timeout: 30) ⇒ CircuitBreaker
Returns a new instance of CircuitBreaker.
20 21 22 23 24 25 26 27 |
# File 'lib/fizzy/circuit_breaker.rb', line 20 def initialize(threshold: 5, timeout: 30) @threshold = threshold @timeout = timeout @failure_count = 0 @last_failure_at = nil @state = :closed @mutex = Mutex.new end |
Instance Method Details
#call { ... } ⇒ Object
Executes the block through the circuit breaker.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/fizzy/circuit_breaker.rb', line 39 def call half_open_probe = false @mutex.synchronize do case effective_state when :open raise Fizzy::APIError.new( "Circuit breaker is open", retryable: true, hint: "Service appears unavailable, will retry after #{@timeout}s" ) when :half_open half_open_probe = true @state = :half_open end end if half_open_probe # Single-probe: hold the probe flag so concurrent callers see :half_open # and block (they'll see :open until this probe completes). @mutex.synchronize { @state = :open } begin result = yield record_success return result rescue Fizzy::NetworkError, Fizzy::APIError => e record_failure if e.retryable? raise end end begin result = yield record_success result rescue Fizzy::NetworkError, Fizzy::APIError => e record_failure if e.retryable? raise end end |
#reset ⇒ Object
Resets the circuit breaker to closed state.
81 82 83 84 85 86 87 |
# File 'lib/fizzy/circuit_breaker.rb', line 81 def reset @mutex.synchronize do @failure_count = 0 @last_failure_at = nil @state = :closed end end |
#state ⇒ Symbol
Returns current circuit state (:closed, :open, :half_open).
30 31 32 |
# File 'lib/fizzy/circuit_breaker.rb', line 30 def state @mutex.synchronize { effective_state } end |