Class: CircuitBreaker::CircuitHandler
- Inherits:
-
Object
- Object
- CircuitBreaker::CircuitHandler
- Defined in:
- lib/circuit_breaker/circuit_handler.rb
Overview
CircuitHandler is stateless, so the circuit_state gets mixed in with the calling object.
Constant Summary collapse
- DEFAULT_FAILURE_THRESHOLD =
5
- DEFAULT_FAILURE_TIMEOUT =
5
- DEFAULT_INVOCATION_TIMEOUT =
30
- DEFAULT_EXCLUDED_EXCEPTIONS =
[]
Instance Attribute Summary collapse
-
#excluded_exceptions ⇒ Object
The exceptions which should be ignored if happens, they are not counted as failures.
-
#failure_threshold ⇒ Object
The number of failures needed to trip the breaker.
-
#failure_timeout ⇒ Object
The period of time in seconds before attempting to reset the breaker.
-
#invocation_timeout ⇒ Object
The period of time the circuit_method has to return before a timeout exception is thrown.
-
#logger ⇒ Object
Optional logger.
Instance Method Summary collapse
-
#handle(circuit_state, method, *args) ⇒ Object
Handles the method covered by the circuit breaker.
-
#initialize(logger = nil) ⇒ CircuitHandler
constructor
A new instance of CircuitHandler.
-
#is_failure_threshold_reached(circuit_state) ⇒ Object
Returns true when the number of failures is sufficient to trip the breaker, false otherwise.
-
#is_timeout_exceeded(circuit_state) ⇒ Object
Returns true if enough time has elapsed since the last failure time, false otherwise.
-
#is_tripped(circuit_state) ⇒ Object
Returns true if the circuit breaker is still open and the timeout has not been exceeded, false otherwise.
-
#new_circuit_state ⇒ Object
Returns a new CircuitState instance.
-
#on_circuit_open(circuit_state) ⇒ Object
Called when a call is made and the circuit is open.
-
#on_failure(circuit_state) ⇒ Object
Called when an individual failure happens.
-
#on_success(circuit_state) ⇒ Object
Called when an individual success happens.
Constructor Details
#initialize(logger = nil) ⇒ CircuitHandler
Returns a new instance of CircuitHandler.
41 42 43 44 45 46 47 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 41 def initialize(logger = nil) @logger = logger @failure_threshold = DEFAULT_FAILURE_THRESHOLD @failure_timeout = DEFAULT_FAILURE_TIMEOUT @invocation_timeout = DEFAULT_INVOCATION_TIMEOUT @excluded_exceptions = DEFAULT_EXCLUDED_EXCEPTIONS end |
Instance Attribute Details
#excluded_exceptions ⇒ Object
The exceptions which should be ignored if happens, they are not counted as failures
29 30 31 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 29 def excluded_exceptions @excluded_exceptions end |
#failure_threshold ⇒ Object
The number of failures needed to trip the breaker.
14 15 16 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 14 def failure_threshold @failure_threshold end |
#failure_timeout ⇒ Object
The period of time in seconds before attempting to reset the breaker.
19 20 21 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 19 def failure_timeout @failure_timeout end |
#invocation_timeout ⇒ Object
The period of time the circuit_method has to return before a timeout exception is thrown.
24 25 26 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 24 def invocation_timeout @invocation_timeout end |
#logger ⇒ Object
Optional logger.
34 35 36 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 34 def logger @logger end |
Instance Method Details
#handle(circuit_state, method, *args) ⇒ Object
Handles the method covered by the circuit breaker.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 59 def handle(circuit_state, method, *args) if is_tripped(circuit_state) @logger.debug("handle: breaker is tripped, refusing to execute: #{circuit_state.inspect}") if @logger on_circuit_open(circuit_state) end begin out = nil Timeout.timeout(@invocation_timeout, CircuitBreaker::CircuitBrokenException) do out = method[*args] on_success(circuit_state) end rescue Exception => e on_failure(circuit_state) unless @excluded_exceptions.include?(e.class) raise end return out end |
#is_failure_threshold_reached(circuit_state) ⇒ Object
Returns true when the number of failures is sufficient to trip the breaker, false otherwise.
81 82 83 84 85 86 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 81 def is_failure_threshold_reached(circuit_state) out = (circuit_state.failure_count > failure_threshold) @logger.debug("is_failure_threshold_reached: #{circuit_state.failure_count} > #{failure_threshold} == #{out}") if @logger return out end |
#is_timeout_exceeded(circuit_state) ⇒ Object
Returns true if enough time has elapsed since the last failure time, false otherwise.
91 92 93 94 95 96 97 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 91 def is_timeout_exceeded(circuit_state) now = Time.now time_since = now - circuit_state.last_failure_time @logger.debug("timeout_exceeded: time since last failure = #{time_since.inspect}") if @logger return time_since >= failure_timeout end |
#is_tripped(circuit_state) ⇒ Object
Returns true if the circuit breaker is still open and the timeout has not been exceeded, false otherwise.
103 104 105 106 107 108 109 110 111 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 103 def is_tripped(circuit_state) if circuit_state.open? && is_timeout_exceeded(circuit_state) @logger.debug("is_tripped: attempting reset into half open state for #{circuit_state.inspect}") if @logger circuit_state.attempt_reset end return circuit_state.open? end |
#new_circuit_state ⇒ Object
Returns a new CircuitState instance.
52 53 54 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 52 def new_circuit_state ::CircuitBreaker::CircuitState.new end |
#on_circuit_open(circuit_state) ⇒ Object
Called when a call is made and the circuit is open. Raises a CircuitBrokenException exception.
148 149 150 151 152 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 148 def on_circuit_open(circuit_state) @logger.debug("on_circuit_open: raising for #{circuit_state.inspect}") if @logger raise CircuitBreaker::CircuitBrokenException.new("Circuit broken, please wait for timeout", circuit_state) end |
#on_failure(circuit_state) ⇒ Object
Called when an individual failure happens.
133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 133 def on_failure(circuit_state) @logger.debug("on_failure: circuit_state = #{circuit_state.inspect}") if @logger circuit_state.increment_failure_count if is_failure_threshold_reached(circuit_state) || circuit_state.half_open? # Set us into a closed state. @logger.debug("on_failure: tripping circuit breaker #{circuit_state.inspect}") if @logger circuit_state.trip end end |
#on_success(circuit_state) ⇒ Object
Called when an individual success happens.
116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/circuit_breaker/circuit_handler.rb', line 116 def on_success(circuit_state) @logger.debug("on_success: #{circuit_state.inspect}") if @logger if circuit_state.closed? @logger.debug("on_success: reset_failure_count #{circuit_state.inspect}") if @logger circuit_state.reset_failure_count end if circuit_state.half_open? @logger.debug("on_success: reset circuit #{circuit_state.inspect}") if @logger circuit_state.reset end end |