simple_circuit_breaker 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -4,6 +4,11 @@
4
4
 
5
5
  Simple Ruby implementation of the [Circuit Breaker design pattern][0].
6
6
 
7
+ This implementation aims to be as simple as possible. It does not have external
8
+ dependencies and only handles the core circuit breaker functionality. Wrapping
9
+ backend calls in timeouts and other exception handling is left to the user of
10
+ the library.
11
+
7
12
  ## Usage
8
13
 
9
14
  ```ruby
@@ -11,13 +16,26 @@ failure_threshold = 3 # Trip the circuit after 3 consecutive failures.
11
16
  retry_timeout = 10 # Retry on an open circuit after 10 seconds.
12
17
  circuit_breaker = SimpleCircuitBreaker.new(failure_threshold, retry_timeout)
13
18
 
19
+ # By default, all exceptions will trip the circuit.
14
20
  circuit_breaker.handle do
15
- FakeClient.new.request
21
+ FooClient.new.request
22
+ end
23
+
24
+ # Setting explicit exceptions that trip the circuit:
25
+ circuit_breaker.handle FooError, BarError do
26
+ FooClient.new.request
16
27
  end
17
28
  ```
18
29
 
19
- `SimpleCircuitBreaker#handle` raises a `SimpleCircuitBreaker::Error` when the
20
- circuit is open.
30
+ `SimpleCircuitBreaker#handle` raises a `SimpleCircuitBreaker::CircuitOpenError`
31
+ when the circuit is open. Otherwise, it re-raises any exceptions that occur in
32
+ the block.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ gem install simple_circuit_breaker
38
+ ```
21
39
 
22
40
  ## Testing
23
41
 
@@ -33,9 +51,16 @@ rake
33
51
 
34
52
  Julius Volz (julius@soundcloud.com), Tobias Schmidt (ts@soundcloud.com).
35
53
 
54
+ ## Alternatives
55
+
56
+ * [Circuit Breaker][2]: heavily customizable circuit handler
57
+ * [CircuitB][3]: supports keeping global circuit state in memcached
58
+
36
59
  ## Contributing
37
60
 
38
61
  Pull requests welcome!
39
62
 
40
63
  [0]: http://en.wikipedia.org/wiki/Circuit_breaker_design_pattern
41
64
  [1]: http://travis-ci.org/soundcloud/simple_circuit_breaker
65
+ [2]: https://github.com/wsargent/circuit_breaker
66
+ [3]: https://github.com/alg/circuit_b
@@ -1,7 +1,7 @@
1
1
  class SimpleCircuitBreaker
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
 
4
- class Error < StandardError
4
+ class CircuitOpenError < StandardError
5
5
  end
6
6
 
7
7
  attr_reader :failure_threshold, :retry_timeout
@@ -12,21 +12,23 @@ class SimpleCircuitBreaker
12
12
  reset!
13
13
  end
14
14
 
15
- def handle(&block)
15
+ def handle(*exceptions, &block)
16
16
  if tripped?
17
- raise Error, 'Circuit is open'
17
+ raise CircuitOpenError, 'Circuit is open'
18
18
  else
19
- execute(&block)
19
+ execute(exceptions, &block)
20
20
  end
21
21
  end
22
22
 
23
23
  protected
24
24
 
25
- def execute(&block)
25
+ def execute(exceptions, &block)
26
26
  begin
27
27
  yield.tap { success! }
28
- rescue Exception
29
- fail!
28
+ rescue Exception => exception
29
+ if exceptions.empty? || exceptions.include?(exception.class)
30
+ fail!
31
+ end
30
32
  raise
31
33
  end
32
34
  end
@@ -0,0 +1,18 @@
1
+ require './lib/simple_circuit_breaker'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'simple_circuit_breaker'
5
+ s.version = SimpleCircuitBreaker::VERSION
6
+ s.platform = Gem::Platform::RUBY
7
+ s.summary = 'Ruby Circuit Breaker implementation'
8
+ s.description = 'Simple Ruby implementation of the Circuit Breaker design pattern'
9
+ s.authors = ['Julius Volz', 'Tobias Schmidt']
10
+ s.email = 'julius@soundcloud.com ts@soundcloud.com'
11
+ s.homepage = 'http://github.com/soundcloud/simple_circuit_breaker'
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- test/*`.split("\n")
15
+ s.require_path = 'lib'
16
+
17
+ s.required_ruby_version = '>= 1.9'
18
+ end
@@ -32,7 +32,7 @@ describe SimpleCircuitBreaker do
32
32
  foo.must_equal 42
33
33
  end
34
34
 
35
- it 'opens after 3 consecutive failures' do
35
+ it 'opens after 3 consecutive failures with no explicit handled exceptions' do
36
36
  3.times do
37
37
  begin
38
38
  @breaker.handle { raise RuntimeError }
@@ -42,9 +42,36 @@ describe SimpleCircuitBreaker do
42
42
 
43
43
  Proc.new do
44
44
  @breaker.handle do
45
- raiseRuntimeError
45
+ raise RuntimeError
46
+ end
47
+ end.must_raise SimpleCircuitBreaker::CircuitOpenError
48
+ end
49
+
50
+ it 'opens after 3 consecutive failures for handled exception' do
51
+ 3.times do
52
+ begin
53
+ @breaker.handle(RuntimeError) { raise RuntimeError }
54
+ rescue RuntimeError
55
+ end
56
+ end
57
+
58
+ Proc.new do
59
+ @breaker.handle(RuntimeError) do
60
+ raise RuntimeError
61
+ end
62
+ end.must_raise SimpleCircuitBreaker::CircuitOpenError
63
+ end
64
+
65
+ it 'doesn\'t open after 3 consecutive failures for non-handled exception' do
66
+ class FooError < Exception
67
+ end
68
+
69
+ 4.times do
70
+ begin
71
+ @breaker.handle(FooError) { raise RuntimeError }
72
+ rescue RuntimeError
46
73
  end
47
- end.must_raise SimpleCircuitBreaker::Error
74
+ end
48
75
  end
49
76
  end
50
77
 
@@ -55,7 +82,7 @@ describe SimpleCircuitBreaker do
55
82
  @breaker.handle { raise RuntimeError } rescue nil
56
83
  end
57
84
 
58
- lambda { @breaker.handle {} }.must_raise SimpleCircuitBreaker::Error
85
+ lambda { @breaker.handle {} }.must_raise SimpleCircuitBreaker::CircuitOpenError
59
86
  end
60
87
 
61
88
  it 'closes after timeout and subsequent success' do
@@ -73,7 +100,7 @@ describe SimpleCircuitBreaker do
73
100
  end
74
101
  end.must_raise RuntimeError
75
102
 
76
- lambda { @breaker.handle {} }.must_raise SimpleCircuitBreaker::Error
103
+ lambda { @breaker.handle {} }.must_raise SimpleCircuitBreaker::CircuitOpenError
77
104
  end
78
105
  end
79
106
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_circuit_breaker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-11-06 00:00:00.000000000 Z
13
+ date: 2012-11-07 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: Simple Ruby implementation of the Circuit Breaker design pattern
16
16
  email: julius@soundcloud.com ts@soundcloud.com
@@ -23,6 +23,7 @@ files:
23
23
  - README.md
24
24
  - Rakefile
25
25
  - lib/simple_circuit_breaker.rb
26
+ - simple_circuit_breaker.gemspec
26
27
  - test/simple_circuit_breaker_test.rb
27
28
  homepage: http://github.com/soundcloud/simple_circuit_breaker
28
29
  licenses: []