class CircuitBreaker::Shield

Attributes

failure_count[R]
failure_threshold[R]
failure_threshold_percentage[R]
invocation_timeout[R]
retry_timeout[R]
total_count[R]

Public Class Methods

new(**options) click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 16
def initialize(**options)
  @failure_count = 0
  @total_count = 0
  @failure_threshold = options.fetch(:failure_threshold, config.failure_threshold)
  @failure_threshold_percentage = options.fetch(:failure_threshold_percentage, config.failure_threshold_percentage)
  @invocation_timeout = options.fetch(:invocation_timeout, config.invocation_timeout)
  @retry_timeout = options.fetch(:retry_timeout, config.retry_timeout)
  @callback = options[:callback]
end

Public Instance Methods

config() click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 26
def config
  CircuitBreaker.config
end
protect(options = {}, &block) click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 34
def protect(options = {}, &block)
  update_config!(options)

  case prev_state = state
  when States::CLOSED, States::HALF_OPEN
    connect(&block)
  when States::OPEN
    raise CircuitBreaker::Open
  end
end
update_config!(options) click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 30
def update_config!(options)
  CircuitBreaker::Config.update(self, options)
end

Private Instance Methods

connect(&block) click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 75
def connect(&block)
  begin
    result = nil
    ::Timeout::timeout(invocation_timeout) do
      start_time = Time.now
      result = block.call
      duration = Time.now - start_time
      invoke_callback(result, duration: duration)
      reset
    end
  rescue ::Timeout::Error => e
    record_failure
    invoke_callback
    raise CircuitBreaker::TimeoutError
  ensure
    increment_total_count
  end

  result
end
increment_total_count() click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 96
def increment_total_count
  @total_count += 1
end
invoke_callback(result = nil, options = {}) click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 105
def invoke_callback(result = nil, options = {})
  @callback.respond_to?(:call) && @callback.call(result, options)
end
reached_failure_threshold?() click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 57
def reached_failure_threshold?
  (failure_count >= failure_threshold)
end
reached_failure_threshold_percentage?() click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 61
def reached_failure_threshold_percentage?
  (total_count.nonzero? && (failure_count.to_f / total_count.to_f) >= failure_threshold_percentage)
end
reached_retry_timeout?() click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 65
def reached_retry_timeout?
  (Time.now - @last_failure_time) > @retry_timeout
end
record_failure() click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 100
def record_failure
  @last_failure_time = Time.now
  @failure_count += 1
end
reset() click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 69
def reset
  @failure_count = 0
  @total_count = 0
  @state = States::CLOSED
end
state() click to toggle source
# File lib/circuit_breaker-ruby/shield.rb, line 47
def state
  if reached_failure_threshold? && reached_failure_threshold_percentage? && reached_retry_timeout?
    States::HALF_OPEN
  elsif reached_failure_threshold? && reached_failure_threshold_percentage?
    States::OPEN
  else
    States::CLOSED
  end
end