class SwitchGear::CircuitBreaker::Redis

Attributes

circuit[RW]

(look to {SwitchGear::CircuitBreaker::Memory#circuit})

client[RW]

An instance of an redis client. This library does not have a hard dependency on a particular redis client but for testing I've used [redis-rb](github.com/redis/redis-rb). Whatever you pass in here simply has to implement a few redis commands such as `sadd`, `del`, `smembers`, `get` and `set`. The client will ensure these exist before the breaker can be instantiated. @return [Object] - redis client given

failure_limit[RW]

(look to {SwitchGear::CircuitBreaker::Memory#failure_limit})

failures[RW]

(look to {SwitchGear::CircuitBreaker::Memory#failures})

logger[RW]

(look to {SwitchGear::CircuitBreaker::Memory#logger})

namespace[RW]

A unique name that will be used across servers to sync state and failures. I'd recommend `your_class.name:your_method_name` or whatever is special about what's being invoked in the `circuit`. See examples/example_redis.rb @return [String] - namespace given

reset_timeout[RW]

(look to {SwitchGear::CircuitBreaker::Memory#reset_timeout})

state[RW]

(look to {SwitchGear::CircuitBreaker::Memory#state})

Public Class Methods

new() { |self| ... } click to toggle source

The main class to instantiate the CircuitBraker class.

@example create a new breaker

breaker = SwitchGear::CircuitBreaker::Redis.new do |cb|
  cb.circuit = -> (arg) { my_method(arg) }
  cb.failure_limit = 2
  cb.reset_timeout = 5
  cb.client = redis_client
  cb.namespace = "some_key"
end

@yieldparam circuit - (look to {#circuit}) @yieldparam failure_limit - (look to {#failure_limit}) @yieldparam reset_timeout - (look to {#reset_timeout}) @yieldparam logger - (look to {#logger}) @yieldparam client - (look to {#client}) @yieldparam namespace - (look to {#namespace}) @return [SwitchGear::CircuitBreaker::Redis] the object.

# File lib/switch_gear/circuit_breaker/redis.rb, line 49
def initialize
  yield self
  @client = client
  @namespace = namespace
  @failure_limit ||= 5
  @reset_timeout ||= 10
  @logger = Logger.new(STDOUT)
  run_validations
  @namespace = "circuit_breaker:#{namespace}"
end

Public Instance Methods

add_failure(failure) click to toggle source
# File lib/switch_gear/circuit_breaker/redis.rb, line 89
def add_failure(failure)
  client.rpush(fail_namespace, failure.to_json)
end
failure_count() click to toggle source
# File lib/switch_gear/circuit_breaker/redis.rb, line 71
def failure_count
  client.llen(fail_namespace)
end
failures=(failures) click to toggle source

failures= requires we replace what is currently in redis with the new value so we delete all entries first then add

# File lib/switch_gear/circuit_breaker/redis.rb, line 95
def failures=(failures)
  client.del(fail_namespace)
  failures.each { |f| client.rpush(fail_namespace, f.to_json) }
end
most_recent_failure() click to toggle source
# File lib/switch_gear/circuit_breaker/redis.rb, line 75
def most_recent_failure
  Failure.from_json(client.lindex(fail_namespace, -1))
end
state=(state) click to toggle source
# File lib/switch_gear/circuit_breaker/redis.rb, line 67
def state=(state)
  client.set(state_namespace, state.to_s)
end

Private Instance Methods

fail_namespace() click to toggle source
# File lib/switch_gear/circuit_breaker/redis.rb, line 102
def fail_namespace
  "#{namespace}:failures"
end
run_validations() click to toggle source
# File lib/switch_gear/circuit_breaker/redis.rb, line 110
def run_validations
  # call super to ensure module has what it needs
  super
  redis_commands = [:rpush, :lindex, :llen, :del, :set, :get]
  if !redis_commands.all? { |c| client.respond_to?(c) }
    raise NotImplementedError.new("Missing Methods.  Your client must implement: #{redis_commands}")
  end
  if !namespace
    raise NotImplementedError.new("Missing namespace")
  end
end
state_namespace() click to toggle source
# File lib/switch_gear/circuit_breaker/redis.rb, line 106
def state_namespace
  "#{namespace}:state"
end