Skip to content

Instantly share code, notes, and snippets.

@halorgium
Last active December 15, 2015 12:49
Show Gist options
  • Save halorgium/0e12f28337f80cb959e4 to your computer and use it in GitHub Desktop.
Save halorgium/0e12f28337f80cb959e4 to your computer and use it in GitHub Desktop.
circuit breaker in Celluloid depends on https://github.com/wsargent/circuit_breaker
require 'celluloid'
require 'celluloid/proxies/circuit_breaker'
def safely
p yield
rescue StandardError
p $!
end
class Foo
include Celluloid
def win
1
end
def slow
sleep 4
2
end
def lose
abort "lose"
end
end
foo = Foo.new
class Handler
end
breaker = Celluloid::CircuitBreaker.new(foo) do |config|
config.invocation_timeout = 3
end
safely { breaker.win }
safely { breaker.win }
safely { breaker.win }
10.times do
safely { breaker.lose }
end
10.times do
safely { breaker.win }
sleep 1
end
safely { breaker.slow }
safely { breaker.win }
require 'circuit_breaker' # from https://github.com/wsargent/circuit_breaker
module Celluloid
class CircuitBreaker < AbstractProxy
class Handler < ::CircuitBreaker::CircuitHandler
def initialize(proxy, logger = nil)
super(logger)
@proxy = proxy
end
def handle(circuit_state, meth, *args, &block)
if is_tripped(circuit_state)
@logger.debug("handle: breaker is tripped, refusing to execute: #{circuit_state.inspect}") if @logger
on_circuit_open(circuit_state)
end
begin
out = nil
future = @proxy.future meth, *args, &block
out = future.value(@invocation_timeout)
on_success(circuit_state)
rescue Exception
on_failure(circuit_state)
raise
end
return out
end
end
def initialize(proxy)
@proxy = proxy
@klass = proxy.class.to_s
@handler = Handler.new(@proxy, ::Celluloid::Logger)
yield @handler if block_given?
@state = @handler.new_circuit_state
end
def inspect
"#<Celluloid::CircuitBreaker(#{@klass})>"
end
def method_missing(meth, *args, &block)
@handler.handle(@state, meth, *args, &block)
end
end
end
D, [2013-03-29T01:15:30.361250 #26911] DEBUG -- : on_success: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=nil, @aasm_current_state=:closed>
D, [2013-03-29T01:15:30.361391 #26911] DEBUG -- : on_success: reset_failure_count #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=nil, @aasm_current_state=:closed>
1
D, [2013-03-29T01:15:30.361794 #26911] DEBUG -- : on_success: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=nil, @aasm_current_state=:closed>
D, [2013-03-29T01:15:30.361853 #26911] DEBUG -- : on_success: reset_failure_count #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=nil, @aasm_current_state=:closed>
1
D, [2013-03-29T01:15:30.362234 #26911] DEBUG -- : on_success: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=nil, @aasm_current_state=:closed>
D, [2013-03-29T01:15:30.362340 #26911] DEBUG -- : on_success: reset_failure_count #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=nil, @aasm_current_state=:closed>
1
D, [2013-03-29T01:15:30.362823 #26911] DEBUG -- : on_failure: circuit_state = #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=nil, @aasm_current_state=:closed>
D, [2013-03-29T01:15:30.362879 #26911] DEBUG -- : is_failure_threshold_reached: 1 > 5 == false
#<RuntimeError: lose>
D, [2013-03-29T01:15:30.363390 #26911] DEBUG -- : on_failure: circuit_state = #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=1, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:30.363463 #26911] DEBUG -- : is_failure_threshold_reached: 2 > 5 == false
#<RuntimeError: lose>
D, [2013-03-29T01:15:30.363931 #26911] DEBUG -- : on_failure: circuit_state = #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=2, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:30.363982 #26911] DEBUG -- : is_failure_threshold_reached: 3 > 5 == false
#<RuntimeError: lose>
D, [2013-03-29T01:15:30.364424 #26911] DEBUG -- : on_failure: circuit_state = #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=3, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:30.364473 #26911] DEBUG -- : is_failure_threshold_reached: 4 > 5 == false
#<RuntimeError: lose>
D, [2013-03-29T01:15:30.364939 #26911] DEBUG -- : on_failure: circuit_state = #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=4, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:30.364989 #26911] DEBUG -- : is_failure_threshold_reached: 5 > 5 == false
#<RuntimeError: lose>
D, [2013-03-29T01:15:30.365429 #26911] DEBUG -- : on_failure: circuit_state = #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=5, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:30.365479 #26911] DEBUG -- : is_failure_threshold_reached: 6 > 5 == true
D, [2013-03-29T01:15:30.365535 #26911] DEBUG -- : on_failure: tripping circuit breaker #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
#<RuntimeError: lose>
D, [2013-03-29T01:15:30.365801 #26911] DEBUG -- : timeout_exceeded: time since last failure = 0.000301
D, [2013-03-29T01:15:30.365863 #26911] DEBUG -- : handle: breaker is tripped, refusing to execute: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
D, [2013-03-29T01:15:30.365918 #26911] DEBUG -- : on_circuit_open: raising for #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
#<CircuitBreaker::CircuitBrokenException: Circuit broken, please wait for timeout>
D, [2013-03-29T01:15:30.365997 #26911] DEBUG -- : timeout_exceeded: time since last failure = 0.000514
D, [2013-03-29T01:15:30.366054 #26911] DEBUG -- : handle: breaker is tripped, refusing to execute: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
D, [2013-03-29T01:15:30.366107 #26911] DEBUG -- : on_circuit_open: raising for #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
#<CircuitBreaker::CircuitBrokenException: Circuit broken, please wait for timeout>
D, [2013-03-29T01:15:30.366178 #26911] DEBUG -- : timeout_exceeded: time since last failure = 0.000695
D, [2013-03-29T01:15:30.366234 #26911] DEBUG -- : handle: breaker is tripped, refusing to execute: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
D, [2013-03-29T01:15:30.366287 #26911] DEBUG -- : on_circuit_open: raising for #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
#<CircuitBreaker::CircuitBrokenException: Circuit broken, please wait for timeout>
D, [2013-03-29T01:15:30.366355 #26911] DEBUG -- : timeout_exceeded: time since last failure = 0.000873
D, [2013-03-29T01:15:30.366411 #26911] DEBUG -- : handle: breaker is tripped, refusing to execute: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
D, [2013-03-29T01:15:30.366464 #26911] DEBUG -- : on_circuit_open: raising for #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
#<CircuitBreaker::CircuitBrokenException: Circuit broken, please wait for timeout>
D, [2013-03-29T01:15:30.366535 #26911] DEBUG -- : timeout_exceeded: time since last failure = 0.001053
D, [2013-03-29T01:15:30.366591 #26911] DEBUG -- : handle: breaker is tripped, refusing to execute: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
D, [2013-03-29T01:15:30.366644 #26911] DEBUG -- : on_circuit_open: raising for #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
#<CircuitBreaker::CircuitBrokenException: Circuit broken, please wait for timeout>
D, [2013-03-29T01:15:31.368075 #26911] DEBUG -- : timeout_exceeded: time since last failure = 1.002402
D, [2013-03-29T01:15:31.368634 #26911] DEBUG -- : handle: breaker is tripped, refusing to execute: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
D, [2013-03-29T01:15:31.369249 #26911] DEBUG -- : on_circuit_open: raising for #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
#<CircuitBreaker::CircuitBrokenException: Circuit broken, please wait for timeout>
D, [2013-03-29T01:15:32.370125 #26911] DEBUG -- : timeout_exceeded: time since last failure = 2.004575
D, [2013-03-29T01:15:32.370441 #26911] DEBUG -- : handle: breaker is tripped, refusing to execute: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
D, [2013-03-29T01:15:32.370726 #26911] DEBUG -- : on_circuit_open: raising for #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
#<CircuitBreaker::CircuitBrokenException: Circuit broken, please wait for timeout>
D, [2013-03-29T01:15:33.371245 #26911] DEBUG -- : timeout_exceeded: time since last failure = 3.005714
D, [2013-03-29T01:15:33.371443 #26911] DEBUG -- : handle: breaker is tripped, refusing to execute: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
D, [2013-03-29T01:15:33.371541 #26911] DEBUG -- : on_circuit_open: raising for #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
#<CircuitBreaker::CircuitBrokenException: Circuit broken, please wait for timeout>
D, [2013-03-29T01:15:34.372426 #26911] DEBUG -- : timeout_exceeded: time since last failure = 4.00681
D, [2013-03-29T01:15:34.372739 #26911] DEBUG -- : handle: breaker is tripped, refusing to execute: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
D, [2013-03-29T01:15:34.373151 #26911] DEBUG -- : on_circuit_open: raising for #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
#<CircuitBreaker::CircuitBrokenException: Circuit broken, please wait for timeout>
D, [2013-03-29T01:15:35.374694 #26911] DEBUG -- : timeout_exceeded: time since last failure = 5.009155
D, [2013-03-29T01:15:35.374953 #26911] DEBUG -- : is_tripped: attempting reset into half open state for #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:open>
D, [2013-03-29T01:15:35.376045 #26911] DEBUG -- : on_success: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:half_open>
D, [2013-03-29T01:15:35.376133 #26911] DEBUG -- : on_success: reset circuit #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=6, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:half_open>
1
D, [2013-03-29T01:15:36.378121 #26911] DEBUG -- : on_success: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:36.378221 #26911] DEBUG -- : on_success: reset_failure_count #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
1
D, [2013-03-29T01:15:37.380429 #26911] DEBUG -- : on_success: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:37.380587 #26911] DEBUG -- : on_success: reset_failure_count #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
1
D, [2013-03-29T01:15:38.383204 #26911] DEBUG -- : on_success: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:38.383497 #26911] DEBUG -- : on_success: reset_failure_count #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
1
D, [2013-03-29T01:15:39.386136 #26911] DEBUG -- : on_success: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:39.386326 #26911] DEBUG -- : on_success: reset_failure_count #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
1
D, [2013-03-29T01:15:43.389012 #26911] DEBUG -- : on_failure: circuit_state = #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=0, @last_failure_time=2013-03-29 01:15:30 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:43.389244 #26911] DEBUG -- : is_failure_threshold_reached: 1 > 5 == false
#<Celluloid::TimeoutError: Timed out>
D, [2013-03-29T01:15:43.390800 #26911] DEBUG -- : on_success: #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=1, @last_failure_time=2013-03-29 01:15:43 +1300, @aasm_current_state=:closed>
D, [2013-03-29T01:15:43.391343 #26911] DEBUG -- : on_success: reset_failure_count #<CircuitBreaker::CircuitState:0x007f91b9849f98 @failure_count=1, @last_failure_time=2013-03-29 01:15:43 +1300, @aasm_current_state=:closed>
1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment