:circuit_breaker plugin: added support for .on_circuit_open callback

called when a circuit is open.

```ruby
HTTPX.plugin(:circuit_breaker).on_circuit_open do |req|
  # ... do smth
end
This commit is contained in:
HoneyryderChuck 2023-06-05 23:03:10 +01:00
parent 03059786b6
commit eb0291ed87
3 changed files with 46 additions and 4 deletions

View File

@ -31,6 +31,16 @@ module HTTPX
@circuit_store = orig.instance_variable_get(:@circuit_store).dup
end
%i[circuit_open].each do |meth|
class_eval(<<-MOD, __FILE__, __LINE__ + 1)
def on_#{meth}(&blk) # def on_circuit_open(&blk)
on(:#{meth}, &blk) # on(:circuit_open, &blk)
end # end
MOD
end
private
def send_requests(*requests)
# @type var short_circuit_responses: Array[response]
short_circuit_responses = []
@ -59,6 +69,12 @@ module HTTPX
end
def on_response(request, response)
emit(:circuit_open, request) if try_circuit_open(request, response)
super
end
def try_circuit_open(request, response)
if response.is_a?(ErrorResponse)
case response.error
when RequestTimeoutError
@ -69,8 +85,6 @@ module HTTPX
elsif (break_on = request.options.circuit_breaker_break_on) && break_on.call(response)
@circuit_store.try_open(request.uri, response)
end
super
end
end

View File

@ -5,7 +5,7 @@ module HTTPX
class CircuitStore
@circuits: Hash[String, Circuit]
def try_open: (generic_uri uri, response response) -> void
def try_open: (generic_uri uri, response response) -> response?
def try_respond: (Request request) -> response?
@ -30,7 +30,7 @@ module HTTPX
def respond: () -> response?
def try_open: (response) -> void
def try_open: (response) -> response?
def try_close: () -> void
@ -52,6 +52,10 @@ module HTTPX
module InstanceMethods
@circuit_store: CircuitStore
private
def try_circuit_open: (Request request, response response) -> response?
end
end

View File

@ -70,6 +70,30 @@ module Requests
assert response1 == response2
end
def test_plugin_circuit_breaker_on_circuit_open
return unless origin.start_with?("http://")
unknown_uri = "http://www.qwwqjqwdjqiwdj.com"
circuit_opened = false
session = HTTPX.plugin(:circuit_breaker,
circuit_breaker_max_attempts: 1,
circuit_breaker_break_in: 2,
circuit_breaker_half_open_drip_rate: 1.0)
.on_circuit_open { circuit_opened = true }
# circuit closed
response1 = session.get(unknown_uri)
verify_error_response(response1)
# circuit open
response2 = session.get(unknown_uri)
verify_error_response(response2)
assert response2 == response1
assert circuit_opened
end
# def test_plugin_circuit_breaker_half_open_drip_rate
# unknown_uri = "http://www.qwwqjqwdjqiwdj.com"