lib/httpx/plugins/circuit_breaker/circuit.rb in httpx-0.24.7 vs lib/httpx/plugins/circuit_breaker/circuit.rb in httpx-1.0.0

- old
+ new

@@ -13,63 +13,87 @@ class Circuit def initialize(max_attempts, reset_attempts_in, break_in, circuit_breaker_half_open_drip_rate) @max_attempts = max_attempts @reset_attempts_in = reset_attempts_in @break_in = break_in - @circuit_breaker_half_open_drip_rate = 1 - circuit_breaker_half_open_drip_rate + @circuit_breaker_half_open_drip_rate = circuit_breaker_half_open_drip_rate @attempts = 0 + + total_real_attempts = @max_attempts * @circuit_breaker_half_open_drip_rate + @drip_factor = (@max_attempts / total_real_attempts).round @state = :closed end def respond try_close case @state when :closed nil when :half_open - # return nothing or smth based on ratio - return if Random.rand >= @circuit_breaker_half_open_drip_rate + @attempts += 1 + # do real requests while drip rate valid + if (@real_attempts % @drip_factor).zero? + @real_attempts += 1 + return + end + @response when :open @response end end def try_open(response) - return unless @state == :closed + case @state + when :closed + now = Utils.now - now = Utils.now + if @attempts.positive? + # reset if error happened long ago + @attempts = 0 if now - @attempted_at > @reset_attempts_in + else + @attempted_at = now + end - if @attempts.positive? - @attempts = 0 if now - @attempted_at > @reset_attempts_in - else - @attempted_at = now - end + @attempts += 1 - @attempts += 1 + return unless @attempts >= @max_attempts - return unless @attempts >= @max_attempts + @state = :open + @opened_at = now + @response = response + when :half_open + # open immediately - @state = :open - @opened_at = now - @response = response + @state = :open + @attempted_at = @opened_at = Utils.now + @response = response + end end def try_close case @state when :closed nil when :half_open + + # do not close circuit unless attempts exhausted + return unless @attempts >= @max_attempts + # reset! @attempts = 0 @opened_at = @attempted_at = @response = nil @state = :closed when :open - @state = :half_open if Utils.elapsed_time(@opened_at) > @break_in + if Utils.elapsed_time(@opened_at) > @break_in + @state = :half_open + @attempts = 0 + @real_attempts = 0 + end end end end end end