class RedisClient::CircuitBreaker
Constants
- OpenCircuitError
Attributes
error_threshold[R]
error_threshold_timeout[R]
error_timeout[R]
success_threshold[R]
Public Class Methods
new(error_threshold:, error_timeout:, error_threshold_timeout: error_timeout, success_threshold: 0)
click to toggle source
# File lib/redis_client/circuit_breaker.rb, line 23 def initialize(error_threshold:, error_timeout:, error_threshold_timeout: error_timeout, success_threshold: 0) @error_threshold = Integer(error_threshold) @error_threshold_timeout = Float(error_threshold_timeout) @error_timeout = Float(error_timeout) @success_threshold = Integer(success_threshold) @errors = [] @successes = 0 @state = :closed @lock = Mutex.new end
Public Instance Methods
protect() { || ... }
click to toggle source
# File lib/redis_client/circuit_breaker.rb, line 34 def protect if @state == :open refresh_state end case @state when :open raise OpenCircuitError, "Too many connection errors happened recently" when :closed begin yield rescue ConnectionError record_error raise end when :half_open begin result = yield record_success result rescue ConnectionError record_error raise end else raise "[BUG] RedisClient::CircuitBreaker unexpected @state (#{@state.inspect}})" end end
Private Instance Methods
record_error()
click to toggle source
# File lib/redis_client/circuit_breaker.rb, line 80 def record_error now = Process.clock_gettime(Process::CLOCK_MONOTONIC) expiry = now - @error_timeout @lock.synchronize do if @state == :closed @errors.reject! { |t| t < expiry } end @errors << now @successes = 0 if @state == :half_open || (@state == :closed && @errors.size >= @error_threshold) @state = :open end end end
record_success()
click to toggle source
# File lib/redis_client/circuit_breaker.rb, line 95 def record_success return unless @state == :half_open @lock.synchronize do return unless @state == :half_open @successes += 1 if @successes >= @success_threshold @state = :closed end end end
refresh_state()
click to toggle source
# File lib/redis_client/circuit_breaker.rb, line 65 def refresh_state now = Process.clock_gettime(Process::CLOCK_MONOTONIC) @lock.synchronize do if @errors.last < (now - @error_timeout) if @success_threshold > 0 @state = :half_open @successes = 0 else @errors.clear @state = :closed end end end end