circuit_breaker 1.0.1 → 1.1.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.
@@ -1,3 +1,7 @@
1
+ === 1.1.0 / 2013-04-18
2
+
3
+ * Feature to ignore specified exceptions (wandenberg)
4
+
1
5
  === 1.0.1 / 2011-01-05
2
6
 
3
7
  * Gem dependency issue "rubyist-aasm" is now "aasm" (ttdonovan)
data/README.txt CHANGED
@@ -44,6 +44,7 @@
44
44
  handler.failure_threshold = 5
45
45
  handler.failure_timeout = 5
46
46
  handler.invocation_timeout = 10
47
+ handler.excluded_exceptions = [NotConsideredFailureException]
47
48
  end
48
49
 
49
50
  # Optional
@@ -5,7 +5,7 @@ require 'circuit_breaker/version'
5
5
  Gem::Specification.new do |s|
6
6
  s.name = %q{circuit_breaker}
7
7
  s.version = CircuitBreaker::VERSION
8
- s.date = %q{2011-01-05}
8
+ s.date = %q{2013-04-13}
9
9
 
10
10
  s.authors = ["Will Sargent"]
11
11
  s.email = ["will.sargent@gmail.com"]
@@ -23,6 +23,11 @@ class CircuitBreaker::CircuitHandler
23
23
  #
24
24
  attr_accessor :invocation_timeout
25
25
 
26
+ #
27
+ # The exceptions which should be ignored if happens, they are not counted as failures
28
+ #
29
+ attr_accessor :excluded_exceptions
30
+
26
31
  #
27
32
  # Optional logger.
28
33
  #
@@ -31,12 +36,14 @@ class CircuitBreaker::CircuitHandler
31
36
  DEFAULT_FAILURE_THRESHOLD = 5
32
37
  DEFAULT_FAILURE_TIMEOUT = 5
33
38
  DEFAULT_INVOCATION_TIMEOUT = 30
39
+ DEFAULT_EXCLUDED_EXCEPTIONS= []
34
40
 
35
41
  def initialize(logger = nil)
36
42
  @logger = logger
37
43
  @failure_threshold = DEFAULT_FAILURE_THRESHOLD
38
44
  @failure_timeout = DEFAULT_FAILURE_TIMEOUT
39
45
  @invocation_timeout = DEFAULT_INVOCATION_TIMEOUT
46
+ @excluded_exceptions = DEFAULT_EXCLUDED_EXCEPTIONS
40
47
  end
41
48
 
42
49
  #
@@ -61,8 +68,8 @@ class CircuitBreaker::CircuitHandler
61
68
  out = method[*args]
62
69
  on_success(circuit_state)
63
70
  end
64
- rescue Exception
65
- on_failure(circuit_state)
71
+ rescue Exception => e
72
+ on_failure(circuit_state) unless @excluded_exceptions.include?(e.class)
66
73
  raise
67
74
  end
68
75
  return out
@@ -1,3 +1,3 @@
1
1
  module CircuitBreaker
2
- VERSION = '1.0.1'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -3,6 +3,9 @@ require 'logger'
3
3
 
4
4
  describe CircuitBreaker do
5
5
 
6
+ class SpecificException < Exception; end
7
+ class NotFoundException < Exception; end
8
+
6
9
  class TestClass
7
10
 
8
11
  include CircuitBreaker
@@ -36,9 +39,17 @@ describe CircuitBreaker do
36
39
  "unresponsive method returned"
37
40
  end
38
41
 
42
+ def raise_specific_error_method
43
+ if @failure == true
44
+ raise SpecificException.new "SPECIFIC FAIL"
45
+ end
46
+
47
+ raise NotFoundException.new "NOT FOUND FAIL"
48
+ end
49
+
39
50
  # Register this method with the circuit breaker...
40
51
  #
41
- circuit_method :call_external_method, :second_method, :unresponsive_method
52
+ circuit_method :call_external_method, :second_method, :unresponsive_method, :raise_specific_error_method
42
53
 
43
54
  #
44
55
  # Define what needs to be set for configuration...
@@ -48,11 +59,13 @@ describe CircuitBreaker do
48
59
  handler.failure_threshold = 5
49
60
  handler.failure_timeout = 5
50
61
  handler.invocation_timeout = 1
62
+ handler.excluded_exceptions = [NotFoundException]
51
63
  end
52
64
 
53
65
  end
54
66
 
55
67
  before(:each) do
68
+ TestClass.circuit_handler.failure_threshold = 5
56
69
  @test_object = TestClass.new()
57
70
  end
58
71
 
@@ -113,9 +126,26 @@ describe CircuitBreaker do
113
126
  @test_object.circuit_state.failure_count.should == 1
114
127
  end
115
128
 
116
- it 'should trip the circuit when the method takes too long to return' do
129
+ it 'should increment the failure count when the method takes too long to return' do
117
130
  lambda { @test_object.unresponsive_method }.should raise_error(CircuitBreaker::CircuitBrokenException)
118
- @test_object.circuit_state.open?.should == true
131
+ @test_object.circuit_state.closed?.should == true
132
+ @test_object.circuit_state.failure_count.should == 1
133
+ end
134
+
135
+ describe "and some exceptions not indicates a circuit problem" do
136
+ it 'should not increment the failure count when a failure of a specific type occurs' do
137
+ @test_object.fail!
138
+
139
+ lambda { @test_object.raise_specific_error_method }.should raise_error(SpecificException)
140
+ @test_object.circuit_state.closed?.should == true
141
+ @test_object.circuit_state.failure_count.should == 1
142
+
143
+ @test_object.succeed!
144
+
145
+ lambda { @test_object.raise_specific_error_method }.should raise_error(NotFoundException)
146
+ @test_object.circuit_state.closed?.should == true
147
+ @test_object.circuit_state.failure_count.should == 1
148
+ end
119
149
  end
120
150
 
121
151
  end
metadata CHANGED
@@ -1,112 +1,87 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: circuit_breaker
3
- version: !ruby/object:Gem::Version
4
- hash: 21
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
5
  prerelease:
6
- segments:
7
- - 1
8
- - 0
9
- - 1
10
- version: 1.0.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Will Sargent
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-01-05 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2013-04-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: aasm
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 0
31
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
32
22
  type: :runtime
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: rake
36
23
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
38
25
  none: false
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- hash: 3
43
- segments:
44
- - 0
45
- version: "0"
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
46
38
  type: :development
47
- version_requirements: *id002
48
- - !ruby/object:Gem::Dependency
49
- name: rspec
50
39
  prerelease: false
51
- requirement: &id003 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
52
41
  none: false
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- hash: 3
57
- segments:
58
- - 0
59
- version: "0"
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
60
54
  type: :development
61
- version_requirements: *id003
62
- description: |-
63
- CircuitBreaker is a relatively simple Ruby mixin that will wrap
64
- a call to a given service in a circuit breaker pattern.
65
-
66
- The circuit starts off "closed" meaning that all calls will go through.
67
- However, consecutive failures are recorded and after a threshold is reached,
68
- the circuit will "trip", setting the circuit into an "open" state.
69
-
70
- In an "open" state, every call to the service will fail by raising
71
- CircuitBrokenException.
72
-
73
- The circuit will remain in an "open" state until the failure timeout has
74
- elapsed.
75
-
76
- After the failure_timeout has elapsed, the circuit will go into
77
- a "half open" state and the call will go through. A failure will
78
- immediately pop the circuit open again, and a success will close the
79
- circuit and reset the failure count.
80
-
81
- require 'circuit_breaker'
82
- class TestService
83
-
84
- include CircuitBreaker
85
-
86
- def call_remote_service() ...
87
-
88
- circuit_method :call_remote_service
89
-
90
- # Optional
91
- circuit_handler do |handler|
92
- handler.logger = Logger.new(STDOUT)
93
- handler.failure_threshold = 5
94
- handler.failure_timeout = 5
95
- end
96
-
97
- # Optional
98
- circuit_handler_class MyCustomCircuitHandler
99
- end
100
- email:
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: ! "CircuitBreaker is a relatively simple Ruby mixin that will wrap\n
63
+ a call to a given service in a circuit breaker pattern.\n\n The circuit starts off
64
+ \"closed\" meaning that all calls will go through.\n However, consecutive failures
65
+ are recorded and after a threshold is reached,\n the circuit will \"trip\", setting
66
+ the circuit into an \"open\" state.\n\n In an \"open\" state, every call to the
67
+ service will fail by raising\n CircuitBrokenException.\n\n The circuit will remain
68
+ in an \"open\" state until the failure timeout has\n elapsed.\n\n After the failure_timeout
69
+ has elapsed, the circuit will go into\n a \"half open\" state and the call will
70
+ go through. A failure will\n immediately pop the circuit open again, and a success
71
+ will close the\n circuit and reset the failure count.\n\n require 'circuit_breaker'\n
72
+ \ class TestService\n\n include CircuitBreaker\n\n def call_remote_service()
73
+ ...\n\n circuit_method :call_remote_service\n\n # Optional\n circuit_handler
74
+ do |handler|\n handler.logger = Logger.new(STDOUT)\n handler.failure_threshold
75
+ = 5\n handler.failure_timeout = 5\n end\n\n # Optional\n circuit_handler_class
76
+ MyCustomCircuitHandler\n end"
77
+ email:
101
78
  - will.sargent@gmail.com
102
79
  executables: []
103
-
104
80
  extensions: []
105
-
106
- extra_rdoc_files:
81
+ extra_rdoc_files:
107
82
  - History.txt
108
83
  - README.txt
109
- files:
84
+ files:
110
85
  - .gitignore
111
86
  - .rspec
112
87
  - Gemfile
@@ -123,39 +98,32 @@ files:
123
98
  - spec/spec_helper.rb
124
99
  homepage: http://github.com/wsargent/circuit_breaker
125
100
  licenses: []
126
-
127
101
  post_install_message:
128
- rdoc_options:
102
+ rdoc_options:
129
103
  - --main
130
104
  - README.txt
131
105
  - --charset=UTF-8
132
- require_paths:
106
+ require_paths:
133
107
  - lib
134
- required_ruby_version: !ruby/object:Gem::Requirement
108
+ required_ruby_version: !ruby/object:Gem::Requirement
135
109
  none: false
136
- requirements:
137
- - - ">="
138
- - !ruby/object:Gem::Version
139
- hash: 3
140
- segments:
141
- - 0
142
- version: "0"
143
- required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
115
  none: false
145
- requirements:
146
- - - ">="
147
- - !ruby/object:Gem::Version
148
- hash: 3
149
- segments:
150
- - 0
151
- version: "0"
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
152
120
  requirements: []
153
-
154
121
  rubyforge_project: will_sargent
155
- rubygems_version: 1.8.10
122
+ rubygems_version: 1.8.23
156
123
  signing_key:
157
124
  specification_version: 3
158
- summary: CircuitBreaker is a relatively simple Ruby mixin that will wrap a call to a given service in a circuit breaker pattern
159
- test_files:
125
+ summary: CircuitBreaker is a relatively simple Ruby mixin that will wrap a call to
126
+ a given service in a circuit breaker pattern
127
+ test_files:
160
128
  - spec/circuit_breaker_spec.rb
161
129
  - spec/spec_helper.rb