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