class Resilient::CircuitBreaker
Attributes
key[R]
open[R]
opened_or_last_checked_at_epoch[R]
properties[R]
Public Class Methods
get(key, properties = nil, registry = nil)
click to toggle source
Public: Returns an instance of circuit breaker based on key and registry. Default registry is used if none is provided. If key does not exist, it is registered. If key does exist, it returns registered instance instead of allocating a new instance in order to ensure that state/metrics are the same per key.
See #initialize for docs on key and properties.
# File lib/resilient/circuit_breaker.rb, line 18 def self.get(key, properties = nil, registry = nil) key = Key.wrap(key) (registry || Registry.default).fetch(key) { new(key, properties) } end
new(key, properties = nil)
click to toggle source
Private: Builds new instance of a CircuitBreaker
.
key - The String or Resilient::Key that determines uniqueness of the circuit breaker in the registry and for instrumentation. properties - The Hash or Resilient::CircuitBreaker::Properties that determine how the circuit breaker should behave. Optional. Defaults to new Resilient::CircuitBreaker::Properties instance.
Returns CircuitBreaker
instance.
# File lib/resilient/circuit_breaker.rb, line 49 def initialize(key, properties = nil) raise ArgumentError, "key argument is required" if key.nil? @key = Key.wrap(key) @properties = Properties.wrap(properties) @open = false @opened_or_last_checked_at_epoch = 0 end
Public Instance Methods
allow_request?()
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 58 def allow_request? instrument("resilient.circuit_breaker.allow_request", key: @key) { |payload| payload[:result] = if payload[:force_open] = @properties.force_open false else # we still want to simulate normal behavior/metrics like open, allow # single request, etc. so it is possible to test properties in # production without impact using force_closed so we run these here # instead of in the else below allow_request = !open? || allow_single_request? if payload[:force_closed] = @properties.force_closed true else allow_request end end } end
failure()
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 90 def failure instrument("resilient.circuit_breaker.failure", key: @key) { |payload| metrics.failure nil } end
reset()
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 97 def reset instrument("resilient.circuit_breaker.reset", key: @key) { |payload| @open = false @opened_or_last_checked_at_epoch = 0 metrics.reset nil } end
success()
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 78 def success instrument("resilient.circuit_breaker.success", key: @key) { |payload| if @open payload[:closed_the_circuit] = true close_circuit else metrics.success end nil } end
Private Instance Methods
allow_single_request?()
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 153 def allow_single_request? instrument("resilient.circuit_breaker.allow_single_request", key: @key) { |payload| now = Time.now.to_i payload[:result] = if @open && now > (@opened_or_last_checked_at_epoch + @properties.sleep_window_seconds) @opened_or_last_checked_at_epoch = now true else false end } end
close_circuit()
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 116 def close_circuit instrument("resilient.circuit_breaker.close_circuit", key: @key) { |payload| @open = false payload[:open] = @open payload[:interval] = Time.now.to_i - @opened_or_last_checked_at_epoch @opened_or_last_checked_at_epoch = 0 } metrics.reset end
instrument(name, payload = {}, &block)
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 166 def instrument(name, payload = {}, &block) properties.instrumenter.instrument(name, payload, &block) end
open?()
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 134 def open? instrument("resilient.circuit_breaker.open", key: @key) { |payload| payload[:result] = if @open true else if under_request_volume_threshold? false else if under_error_threshold_percentage? false else open_circuit true end end end } end
open_circuit()
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 108 def open_circuit instrument("resilient.circuit_breaker.open_circuit", key: @key) { |payload| @opened_or_last_checked_at_epoch = Time.now.to_i @open = true payload[:open] = @open } end
under_error_threshold_percentage?()
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 130 def under_error_threshold_percentage? metrics.under_error_threshold_percentage?(@properties.error_threshold_percentage) end
under_request_volume_threshold?()
click to toggle source
# File lib/resilient/circuit_breaker.rb, line 126 def under_request_volume_threshold? metrics.under_request_volume_threshold?(@properties.request_volume_threshold) end