circuit_breakage 0.2.3 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|