circuit_breaker 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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