circuit_breakage 0.2.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -0
- data/lib/circuit_breakage/breaker.rb +10 -8
- data/lib/circuit_breakage/version.rb +1 -1
- data/spec/breaker_spec.rb +20 -0
- data/spec/redis_backed_breaker_spec.rb +15 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44c83ed5565612433627a4466aa4486ebdf25543
|
4
|
+
data.tar.gz: a0f65eb73e9dd27f832adf19d860e979112efb9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1eaece305ff4a9fb83f1cd4f1a138930b28bde2724bd70c8d0d6fae16a67afa0a94e8514034fe9272133530fb7cd5ad349a264316490ddbf026c2e02e28ea879
|
7
|
+
data.tar.gz: 79ca29de3a040028ff01023c07889ce12fcf88b249fbb694082ce87e48737e3083bbfbd59ba1b875027d3e0965891c68215a0888d6e8ccb0e1fd324b58f6bef1
|
data/README.md
CHANGED
@@ -34,6 +34,32 @@ end
|
|
34
34
|
A "failure" in this context means that the proc either raised an exception or
|
35
35
|
timed out.
|
36
36
|
|
37
|
+
### Example yielding to a block
|
38
|
+
|
39
|
+
As an alternative to initializing the breaker with a block you can
|
40
|
+
use a single breaker with different remote calls by invoking call with a block.
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
class ShapeAPI
|
44
|
+
def initialize
|
45
|
+
@breaker = CircuitBreakage::Breaker.new
|
46
|
+
@breaker.failure_threshold = 3
|
47
|
+
@breaker.duration = 10
|
48
|
+
@breaker.timeout = 0.5
|
49
|
+
@service = ShapeService.new
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_square
|
53
|
+
@breaker.call { @service.get_square_widget }
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_circles(count)
|
57
|
+
@breaker.call { @service.get_circles(count) }
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
37
63
|
### Slightly More Complex Example in Rails
|
38
64
|
|
39
65
|
This example shows one way you might choose to wrap a remote service call in a
|
@@ -15,7 +15,7 @@ module CircuitBreakage
|
|
15
15
|
DEFAULT_DURATION = 300 # Number of seconds the circuit stays tripped
|
16
16
|
DEFAULT_TIMEOUT = 10 # Number of seconds before the call times out
|
17
17
|
|
18
|
-
def initialize(block)
|
18
|
+
def initialize(block=nil)
|
19
19
|
self.block = block
|
20
20
|
self.failure_threshold = DEFAULT_FAILURE_THRESHOLD
|
21
21
|
self.duration = DEFAULT_DURATION
|
@@ -25,30 +25,32 @@ module CircuitBreakage
|
|
25
25
|
self.state ||= 'closed'
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
# Yield the block within the circuit. If no block
|
29
|
+
# is passed use the block passed in at initialization
|
30
|
+
def call(*args, &block_arg)
|
29
31
|
case(state)
|
30
32
|
when 'open'
|
31
33
|
if time_to_retry?
|
32
|
-
do_retry(*args)
|
34
|
+
do_retry(*args, &block_arg)
|
33
35
|
else
|
34
36
|
raise CircuitOpen
|
35
37
|
end
|
36
38
|
when 'closed'
|
37
|
-
do_call(*args)
|
39
|
+
do_call(*args, &block_arg)
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
43
|
private
|
42
44
|
|
43
45
|
# Defined independently so that it can be overridden.
|
44
|
-
def do_retry(*args)
|
45
|
-
do_call(*args)
|
46
|
+
def do_retry(*args, &block_arg)
|
47
|
+
do_call(*args, &block_arg)
|
46
48
|
end
|
47
49
|
|
48
|
-
def do_call(*args)
|
50
|
+
def do_call(*args, &block_arg)
|
49
51
|
ret_value = nil
|
50
52
|
Timeout.timeout(self.timeout) do
|
51
|
-
ret_value = @block.call(*args)
|
53
|
+
ret_value = (block_arg || @block).call(*args)
|
52
54
|
end
|
53
55
|
handle_success
|
54
56
|
|
data/spec/breaker_spec.rb
CHANGED
@@ -9,6 +9,11 @@ module CircuitBreakage
|
|
9
9
|
expect(breaker).to be_a(Breaker)
|
10
10
|
end
|
11
11
|
|
12
|
+
it 'initializes without a block' do
|
13
|
+
breaker = Breaker.new
|
14
|
+
expect(breaker).to be_a(Breaker)
|
15
|
+
end
|
16
|
+
|
12
17
|
describe '#call' do
|
13
18
|
subject { -> { breaker.call(arg) rescue nil} }
|
14
19
|
let(:arg) { 'This is an argument.' }
|
@@ -21,6 +26,21 @@ module CircuitBreakage
|
|
21
26
|
expect(breaker.call(arg)).to eq arg
|
22
27
|
end
|
23
28
|
|
29
|
+
it 'yields the block' do
|
30
|
+
value = breaker.call(arg) do | param |
|
31
|
+
param
|
32
|
+
end
|
33
|
+
expect(value).to eq arg
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'yields the block with dynamic binding variables' do
|
37
|
+
param = 'Felix'
|
38
|
+
value = breaker.call do
|
39
|
+
param.size
|
40
|
+
end
|
41
|
+
expect(value).to eq 'Felix'.size
|
42
|
+
end
|
43
|
+
|
24
44
|
context 'and the call succeeds' do
|
25
45
|
it 'resets the failure count' do
|
26
46
|
breaker.failure_count = 3
|
@@ -20,6 +20,21 @@ module CircuitBreakage
|
|
20
20
|
expect(breaker.call(arg)).to eq arg
|
21
21
|
end
|
22
22
|
|
23
|
+
it 'yields the block' do
|
24
|
+
value = breaker.call(arg) do | param |
|
25
|
+
param
|
26
|
+
end
|
27
|
+
expect(value).to eq arg
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'yields the block with dynamic binding variables' do
|
31
|
+
param = 'Felix'
|
32
|
+
value = breaker.call do
|
33
|
+
param.size
|
34
|
+
end
|
35
|
+
expect(value).to eq 'Felix'.size
|
36
|
+
end
|
37
|
+
|
23
38
|
context 'and the call succeeds' do
|
24
39
|
it 'resets the failure count' do
|
25
40
|
breaker.failure_count = 3
|