circuitbox 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f75524d25326132f1bac120effbfa9b130f95bf1
4
- data.tar.gz: ee8a589ff7b55ea95f5e5d119e7c30fe7be4e640
3
+ metadata.gz: bb9f064a8178b7bfef8be4552f91410d0783acf5
4
+ data.tar.gz: ca1e8126ff01603f881c351c28c47396a8fa7d97
5
5
  SHA512:
6
- metadata.gz: 280e82433f43b428b48ee4e5a5a713da46deb723f8df9d886b3e2bf1e7eb922a119c367a706f66d82ee5d731090580773de06030f451ea40784ae544218e1953
7
- data.tar.gz: 1b64ba171cfe40c0956ed38f94cc3e37c3e848a051cc987a2944b7578362ab5f51992757208dea50559cb5338d3fcff9c7fa2537ba9df047bfb05f1dabbc4038
6
+ metadata.gz: f9e3f74178e1cf6200d5dbbf99925ddb1f235ebf3d287e3c82bd0894d1430b69a4ed062bbaf9afb9cacd5b5707c32cf2dcbd10cd78293b5f438f3b738b956837
7
+ data.tar.gz: fe2a7be07392bd92a0a9e731550f82f1b4e3c6d2ed21759c25d91776e5734d538bb4e7d5bc33da09edd8de5ea2ccdb731e6e8baa36946ea02a7e908415b5c17e
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.1.5
1
+ 2.2.2
data/.travis.yml CHANGED
@@ -4,5 +4,6 @@ rvm:
4
4
  - 2.0.0
5
5
  - 2.1
6
6
  - 2.2
7
+ - 2.2.2
7
8
  before_install:
8
9
  - gem install bundler
data/README.md CHANGED
@@ -66,6 +66,9 @@ class ExampleServiceClient
66
66
 
67
67
  # seconds before the circuit times out
68
68
  timeout_seconds: 1
69
+
70
+ # Logger to use
71
+ logger: Logger.new(STDOUT)
69
72
  })
70
73
  end
71
74
  end
@@ -298,7 +301,9 @@ c.use Circuitbox::FaradayMiddleware, open_circuit: lambda { |response| response.
298
301
  ```
299
302
 
300
303
  ## CHANGELOG
301
- ### version next
304
+ ### v1.1.0
305
+ - ruby 2.2 support [#58](https://github.com/yammer/circuitbox/pull/58)
306
+ - configurable logger [#58](https://github.com/yammer/circuitbox/pull/58)
302
307
 
303
308
  ### v1.0.3
304
309
  - fix timeout issue for default configuration, as default `:Memory` adapter does
@@ -315,7 +320,7 @@ c.use Circuitbox::FaradayMiddleware, open_circuit: lambda { |response| response.
315
320
  removing the related railtie.
316
321
 
317
322
  ### v1.0.0
318
- - support for cross process circuitbreakers by swapping the circuitbreaker store for a
323
+ - support for cross process circuitbreakers by swapping the circuitbreaker store for a
319
324
  `Moneta` supported key value store.
320
325
  - Change `FaradayMiddleware` default behaviour to not open on `4xx` errors but just on `5xx`
321
326
  server errors and connection errors
data/circuitbox.gemspec CHANGED
@@ -3,6 +3,8 @@ lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'circuitbox/version'
5
5
 
6
+ ruby_2_2_2_plus = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.2.2")
7
+
6
8
  Gem::Specification.new do |spec|
7
9
  spec.name = "circuitbox"
8
10
  spec.version = Circuitbox::VERSION
@@ -20,7 +22,11 @@ Gem::Specification.new do |spec|
20
22
 
21
23
  spec.add_development_dependency "bundler"
22
24
  spec.add_development_dependency "rake"
23
- spec.add_development_dependency "rack"
25
+ if ruby_2_2_2_plus
26
+ spec.add_development_dependency "rack"
27
+ else
28
+ spec.add_development_dependency "rack", '< 2'
29
+ end
24
30
  spec.add_development_dependency "gimme"
25
31
  spec.add_development_dependency "minitest"
26
32
  spec.add_development_dependency "mocha"
@@ -33,6 +39,10 @@ Gem::Specification.new do |spec|
33
39
  spec.add_development_dependency "lmdb"
34
40
  spec.add_development_dependency "daybreak"
35
41
 
36
- spec.add_dependency "activesupport"
42
+ if ruby_2_2_2_plus
43
+ spec.add_dependency "activesupport"
44
+ else
45
+ spec.add_dependency "activesupport", '< 5'
46
+ end
37
47
  spec.add_dependency "moneta"
38
48
  end
@@ -20,6 +20,7 @@ class Circuitbox
20
20
  # `timeout_seconds` - seconds until it will timeout the request
21
21
  # `exceptions` - exceptions other than Timeout::Error that count as failures
22
22
  # `time_window` - interval of time used to calculate error_rate (in seconds) - default is 60s
23
+ # `logger` - Logger to use - defaults to Rails.logger if defined, otherwise STDOUT
23
24
  #
24
25
  def initialize(service, options = {})
25
26
  @service = service
@@ -30,7 +31,7 @@ class Circuitbox
30
31
  @exceptions = options.fetch(:exceptions) { [] }
31
32
  @exceptions = [Timeout::Error] if @exceptions.blank?
32
33
 
33
- @logger = defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
34
+ @logger = options.fetch(:logger) { defined?(Rails) ? Rails.logger : Logger.new(STDOUT) }
34
35
  @time_class = options.fetch(:time_class) { Time }
35
36
  sanitize_options
36
37
  end
@@ -1,3 +1,3 @@
1
1
  class Circuitbox
2
- VERSION='1.0.3'
2
+ VERSION='1.1.0'
3
3
  end
@@ -1,26 +1,15 @@
1
1
  require 'test_helper'
2
- require 'ostruct'
3
2
 
4
3
  class CircuitBreakerTest < Minitest::Test
5
- SUCCESSFUL_RESPONSE_STRING = "Success!"
6
- RequestFailureError = Timeout::Error
7
4
  class ConnectionError < StandardError; end;
8
- class SomeOtherError < StandardError; end;
9
5
 
10
6
  def setup
11
7
  Circuitbox::CircuitBreaker.reset
12
8
  end
13
9
 
14
- describe 'initialize' do
15
- it 'force sleep_window to equal time_window if it is too short' do
16
- circuit = Circuitbox::CircuitBreaker.new(:yammer,
17
- :sleep_window => 1,
18
- :time_window => 10
19
- )
20
- assert_equal circuit.option_value(:sleep_window),
21
- circuit.option_value(:time_window),
22
- 'sleep_window has not been corrected properly'
23
- end
10
+ def test_sleep_window_is_forced_to_equal_time_window
11
+ circuit = Circuitbox::CircuitBreaker.new(:yammer, sleep_window: 1, time_window: 10)
12
+ assert_equal circuit.option_value(:sleep_window), circuit.option_value(:time_window)
24
13
  end
25
14
 
26
15
  def test_goes_into_half_open_state_on_sleep
@@ -29,35 +18,28 @@ class CircuitBreakerTest < Minitest::Test
29
18
  assert circuit.send(:half_open?)
30
19
  end
31
20
 
32
-
33
- describe 'ratio' do
34
- def cb_options
35
- {
36
- sleep_window: 300,
37
- volume_threshold: 5,
38
- error_threshold: 33,
39
- timeout_seconds: 1
40
- }
41
- end
42
-
21
+ class Ratio < Minitest::Test
43
22
  def setup
44
23
  Circuitbox::CircuitBreaker.reset
45
- @circuit = Circuitbox::CircuitBreaker.new(:yammer, cb_options)
24
+ @circuit = Circuitbox::CircuitBreaker.new(:yammer,
25
+ sleep_window: 300,
26
+ volume_threshold: 5,
27
+ error_threshold: 33,
28
+ timeout_seconds: 1)
46
29
  end
47
30
 
48
-
49
- it 'open the circuit on 100% failure' do
31
+ def test_open_circuit_on_100_percent_failure
50
32
  run_counter = 0
51
33
  10.times do
52
34
  @circuit.run do
53
35
  run_counter += 1
54
- raise RequestFailureError
36
+ raise Timeout::Error
55
37
  end
56
38
  end
57
39
  assert_equal 6, run_counter, 'the circuit did not open after 6 failures (5 failures + 10%)'
58
40
  end
59
41
 
60
- it 'keep circuit closed on 0% failure' do
42
+ def test_keep_circuit_closed_on_success
61
43
  run_counter = 0
62
44
  10.times do
63
45
  @circuit.run do
@@ -68,12 +50,12 @@ class CircuitBreakerTest < Minitest::Test
68
50
  assert_equal 10, run_counter, 'run block was not executed 10 times'
69
51
  end
70
52
 
71
- it 'open the circuit even after 1 success' do
53
+ def test_open_circuit_on_low_success_rate_below_limit
72
54
  run_counter = 0
73
55
  5.times do
74
56
  @circuit.run do
75
57
  run_counter += 1
76
- raise RequestFailureError
58
+ raise Timeout::Error
77
59
  end
78
60
  end
79
61
 
@@ -84,13 +66,13 @@ class CircuitBreakerTest < Minitest::Test
84
66
  5.times do
85
67
  @circuit.run do
86
68
  run_counter += 1
87
- raise RequestFailureError
69
+ raise Timeout::Error
88
70
  end
89
71
  end
90
72
  assert_equal 5, run_counter, 'the circuit did not open after 5 failures (5 failures + 10%)'
91
73
  end
92
74
 
93
- it 'keep circuit closed when failure ratio do not exceed limit' do
75
+ def test_keep_circuit_closed_on_low_failure_rate_below_failure_limit
94
76
  run_counter = 0
95
77
  7.times do
96
78
  @circuit.run do
@@ -103,14 +85,14 @@ class CircuitBreakerTest < Minitest::Test
103
85
  3.times do
104
86
  @circuit.run do
105
87
  run_counter += 1
106
- raise RequestFailureError
88
+ raise Timeout::Error
107
89
  end
108
90
  end
109
91
  assert_equal 10, run_counter, 'block was not executed 10 times'
110
92
  assert @circuit.error_rate < 33, 'error_rate pass over 33%'
111
93
  end
112
94
 
113
- it 'circuit open when failure ratio exceed limit' do
95
+ def test_open_circuit_on_high_failure_rate_exceeding_failure_limit
114
96
  run_counter = 0
115
97
  10.times do
116
98
  @circuit.run do
@@ -123,79 +105,84 @@ class CircuitBreakerTest < Minitest::Test
123
105
  10.times do
124
106
  @circuit.run do
125
107
  run_counter += 1
126
- raise RequestFailureError
108
+ raise Timeout::Error
127
109
  end
128
110
  end
129
111
  # 5 failure on 15 run is 33%
130
112
  assert_equal 15, run_counter, 'block was not executed 10 times'
131
113
  assert @circuit.error_rate >= 33, 'error_rate pass over 33%'
132
114
  end
133
-
134
115
  end
135
116
 
136
- describe 'exceptions' do
137
- before do
117
+ class Exceptions < Minitest::Test
118
+ class SentinalError < StandardError; end
119
+
120
+ def setup
138
121
  Circuitbox::CircuitBreaker.reset
139
- @circuit = Circuitbox::CircuitBreaker.new(:yammer, exceptions: [SomeOtherError])
122
+ @circuit = Circuitbox::CircuitBreaker.new(:yammer, exceptions: [SentinalError])
140
123
  end
141
124
 
142
- it 'raises exception when circuit is open' do
125
+ def test_raises_when_circuit_is_open
143
126
  @circuit.stubs(open_flag?: true)
144
- -> { @circuit.run! {} }.must_raise Circuitbox::OpenCircuitError
127
+ assert_raises(Circuitbox::OpenCircuitError) { @circuit.run! {} }
145
128
  end
146
129
 
147
- it 'raises exception when service fails' do
148
- err = -> { @circuit.run! { raise SomeOtherError } }.must_raise Circuitbox::ServiceFailureError
149
- err.original.must_be_instance_of SomeOtherError
130
+ def test_raises_on_service_failure
131
+ assert_raises(Circuitbox::ServiceFailureError) { @circuit.run! { raise SentinalError } }
150
132
  end
151
- end
152
133
 
153
- describe 'closing the circuit after sleep' do
154
- def cb_options
155
- {
156
- sleep_window: 1,
157
- time_window: 2,
158
- volume_threshold: 5,
159
- error_threshold: 5,
160
- timeout_seconds: 1
161
- }
134
+ def test_sets_original_error_on_service_failure
135
+ @circuit.run! { raise SentinalError }
136
+ rescue Circuitbox::ServiceFailureError => service_failure_error
137
+ assert_instance_of SentinalError, service_failure_error.original
162
138
  end
139
+ end
163
140
 
141
+ class CloseAfterSleep < Minitest::Test
164
142
  def setup
165
- @circuit = Circuitbox::CircuitBreaker.new(:yammer, cb_options)
143
+ Circuitbox::CircuitBreaker.reset
144
+ @circuit = Circuitbox::CircuitBreaker.new(:yammer,
145
+ sleep_window: 1,
146
+ time_window: 2,
147
+ volume_threshold: 5,
148
+ error_threshold: 5,
149
+ timeout_seconds: 1)
166
150
  end
167
151
 
168
- it 'close the circuit after sleeping time' do
169
- # lets open the circuit
170
- (cb_options[:error_threshold] + 1).times { @circuit.run { raise RequestFailureError } }
152
+ def test_circuit_closes_after_sleep_time_window
153
+ open_circuit!
171
154
  run_count = 0
172
155
  @circuit.run { run_count += 1 }
173
- assert_equal 0, run_count, 'circuit is not open'
156
+ assert_equal 0, run_count, 'circuit has not opened prior'
174
157
  # it is + 2 on purpose, because + 1 is flaky here
175
- sleep cb_options[:sleep_window] + 2
158
+ sleep @circuit.option_value(:sleep_window) + 2
176
159
 
177
160
  @circuit.run { run_count += 1 }
178
- assert_equal 1, run_count, 'circuit is not closed'
161
+ assert_equal 1, run_count, 'circuit did not close after sleep'
162
+ end
163
+
164
+ def open_circuit!
165
+ (@circuit.option_value(:error_threshold) + 1).times { @circuit.run { raise Timeout::Error } }
179
166
  end
180
167
  end
181
168
 
182
- describe "when in half open state" do
183
- before do
169
+ class HalfOpenState < Minitest::Test
170
+ def setup
184
171
  Circuitbox::CircuitBreaker.reset
185
172
  @circuit = Circuitbox::CircuitBreaker.new(:yammer)
186
173
  end
187
174
 
188
- it "opens circuit on next failed request" do
175
+ def test_when_in_half_open_state_circuit_opens_on_failure
189
176
  @circuit.stubs(half_open?: true)
190
177
  @circuit.expects(:open!)
191
- @circuit.run { raise RequestFailureError }
178
+ @circuit.run { raise Timeout::Error }
192
179
  end
193
180
 
194
- it "closes circuit on successful request" do
181
+ def test_when_in_half_open_state_circuit_closes_on_success
195
182
  @circuit.send(:half_open!)
196
183
  @circuit.run { 'success' }
197
- assert !@circuit.send(:half_open?)
198
- assert !@circuit.send(:open?)
184
+ refute @circuit.send(:half_open?)
185
+ refute @circuit.send(:open?)
199
186
  end
200
187
  end
201
188
 
@@ -213,8 +200,8 @@ class CircuitBreakerTest < Minitest::Test
213
200
 
214
201
  def test_should_return_response_if_it_doesnt_timeout
215
202
  circuit = Circuitbox::CircuitBreaker.new(:yammer)
216
- response = emulate_circuit_run(circuit, :success, SUCCESSFUL_RESPONSE_STRING)
217
- assert_equal SUCCESSFUL_RESPONSE_STRING, response
203
+ response = emulate_circuit_run(circuit, :success, "success")
204
+ assert_equal "success", response
218
205
  end
219
206
 
220
207
  def test_timeout_seconds_run_options_overrides_circuit_options
@@ -230,36 +217,37 @@ class CircuitBreakerTest < Minitest::Test
230
217
  end
231
218
 
232
219
  def test_doesnt_catch_out_of_scope_exceptions
233
- circuit = Circuitbox::CircuitBreaker.new(:yammer, :exceptions => [ConnectionError, RequestFailureError])
220
+ sentinal = Class.new(StandardError)
221
+ circuit = Circuitbox::CircuitBreaker.new(:yammer, :exceptions => [ConnectionError, Timeout::Error])
234
222
 
235
- assert_raises SomeOtherError do
236
- emulate_circuit_run(circuit, :failure, SomeOtherError)
223
+ assert_raises(sentinal) do
224
+ emulate_circuit_run(circuit, :failure, sentinal)
237
225
  end
238
226
  end
239
227
 
240
228
  def test_records_response_failure
241
- circuit = Circuitbox::CircuitBreaker.new(:yammer, :exceptions => [RequestFailureError])
229
+ circuit = Circuitbox::CircuitBreaker.new(:yammer, :exceptions => [Timeout::Error])
242
230
  circuit.expects(:log_event).with(:failure)
243
- emulate_circuit_run(circuit, :failure, RequestFailureError)
231
+ emulate_circuit_run(circuit, :failure, Timeout::Error)
244
232
  end
245
233
 
246
234
  def test_records_response_success
247
235
  circuit = Circuitbox::CircuitBreaker.new(:yammer)
248
236
  circuit.expects(:log_event).with(:success)
249
- emulate_circuit_run(circuit, :success, SUCCESSFUL_RESPONSE_STRING)
237
+ emulate_circuit_run(circuit, :success, "success")
250
238
  end
251
239
 
252
240
  def test_does_not_send_request_if_circuit_is_open
253
241
  circuit = Circuitbox::CircuitBreaker.new(:yammer)
254
242
  circuit.stubs(:open? => true)
255
243
  circuit.expects(:yield).never
256
- response = emulate_circuit_run(circuit, :failure, RequestFailureError)
244
+ response = emulate_circuit_run(circuit, :failure, Timeout::Error)
257
245
  assert_equal nil, response
258
246
  end
259
247
 
260
248
  def test_returns_nil_response_on_failed_request
261
249
  circuit = Circuitbox::CircuitBreaker.new(:yammer)
262
- response = emulate_circuit_run(circuit, :failure, RequestFailureError)
250
+ response = emulate_circuit_run(circuit, :failure, Timeout::Error)
263
251
  assert_equal nil, response
264
252
  end
265
253
 
@@ -268,11 +256,11 @@ class CircuitBreakerTest < Minitest::Test
268
256
  circuit.stubs(:open? => true)
269
257
 
270
258
  assert !circuit.send(:open_flag?)
271
- emulate_circuit_run(circuit, :failure, RequestFailureError)
259
+ emulate_circuit_run(circuit, :failure, Timeout::Error)
272
260
  assert circuit.send(:open_flag?)
273
261
 
274
262
  circuit.expects(:open!).never
275
- emulate_circuit_run(circuit, :failure, RequestFailureError)
263
+ emulate_circuit_run(circuit, :failure, Timeout::Error)
276
264
  end
277
265
 
278
266
  def test_open_is_true_if_open_flag
@@ -347,89 +335,80 @@ class CircuitBreakerTest < Minitest::Test
347
335
  assert_equal 0, circuit.send(:success_count)
348
336
  end
349
337
 
350
- describe 'notifications' do
351
-
338
+ class Notifications < Minitest::Test
352
339
  def setup
353
340
  Circuitbox::CircuitBreaker.reset
354
341
  end
355
342
 
356
- def circuit
357
- Circuitbox::CircuitBreaker.new(:yammer, :notifier_class => @notifier)
358
- end
359
-
360
-
361
- it 'notifies on open circuit' do
362
- @notifier = gimme_notifier
363
- c = circuit
364
- 10.times { c.run { raise RequestFailureError }}
365
- assert @notifier.notified?, 'no notification sent'
343
+ def test_notification_on_open
344
+ notifier = gimme_notifier
345
+ circuit = Circuitbox::CircuitBreaker.new(:yammer, notifier_class: notifier)
346
+ 10.times { circuit.run { raise Timeout::Error }}
347
+ assert notifier.notified?, 'no notification sent'
366
348
  end
367
349
 
368
- it 'notifies on close circuit' do
369
- @notifier = gimme_notifier
370
- c = circuit
371
- 5.times { c.run { raise RequestFailureError }}
372
- clear_notified!
373
- 10.times { c.run { 'success' }}
374
- assert @notifier.notified?, 'no notification sent'
350
+ def test_notification_on_close
351
+ notifier = gimme_notifier
352
+ circuit = Circuitbox::CircuitBreaker.new(:yammer, notifier_class: notifier)
353
+ 5.times { circuit.run { raise Timeout::Error }}
354
+ notifier.clear_notified!
355
+ 10.times { circuit.run { 'success' }}
356
+ assert notifier.notified?, 'no notification sent'
375
357
  end
376
358
 
377
- it 'notifies warning if sleep_window is shorter than time_window' do
378
- @notifier = gimme_notifier
359
+ def test_warning_when_sleep_window_is_shorter_than_time_window
360
+ notifier = gimme_notifier
379
361
  Circuitbox::CircuitBreaker.new(:yammer,
380
- :notifier_class => @notifier,
381
- :sleep_window => 1,
382
- :time_window => 10
383
- )
384
- assert @notifier.notified?, 'no notification sent'
362
+ notifier_class: notifier,
363
+ sleep_window: 1,
364
+ time_window: 10)
365
+ assert notifier.notified?, 'no notification sent'
385
366
  end
386
367
 
387
- it 'DO NOT notifies warning if sleep_window is longer than time_window' do
388
- @notifier = gimme_notifier
368
+ def test_does_not_warn_on_sleep_window_being_correctly_sized
369
+ notifier = gimme_notifier
389
370
  Circuitbox::CircuitBreaker.new(:yammer,
390
- :notifier_class => @notifier,
391
- :sleep_window => 11,
392
- :time_window => 10
393
- )
394
- assert_equal false, @notifier.notified?, 'no notification sent'
371
+ notifier_class: notifier,
372
+ sleep_window: 11,
373
+ time_window: 10)
374
+ assert_equal false, notifier.notified?, 'no notification sent'
395
375
  end
396
376
 
397
-
398
- it 'notifies error_rate on error_rate calculation' do
399
- @notifier = gimme_notifier(metric: :error_rate, metric_value: 0.0)
400
- 10.times { circuit.run {'success' }}
401
- assert @notifier.notified?, 'no notification sent'
377
+ def test_notifies_on_success_rate_calculation
378
+ notifier = gimme_notifier(metric: :error_rate, metric_value: 0.0)
379
+ circuit = Circuitbox::CircuitBreaker.new(:yammer, notifier_class: notifier)
380
+ 10.times { circuit.run { "success" } }
381
+ assert notifier.notified?, "no notification sent"
402
382
  end
403
383
 
404
- it 'notifies failure_count on error_rate calculation' do
405
- @notifier = gimme_notifier(metric: :failure_count, metric_value: 1)
406
- 10.times { circuit.run { raise RequestFailureError }}
407
- assert @notifier.notified?, 'no notification sent'
384
+ def test_notifies_on_error_rate_calculation
385
+ notifier = gimme_notifier(metric: :failure_count, metric_value: 1)
386
+ circuit = Circuitbox::CircuitBreaker.new(:yammer, notifier_class: notifier)
387
+ 10.times { circuit.run { raise Timeout::Error }}
388
+ assert notifier.notified?, 'no notification sent'
408
389
  end
409
390
 
410
- it 'notifies success_count on error_rate calculation' do
411
- @notifier = gimme_notifier(metric: :success_count, metric_value: 6)
391
+ def test_success_count_on_error_rate_calculation
392
+ notifier = gimme_notifier(metric: :success_count, metric_value: 6)
393
+ circuit = Circuitbox::CircuitBreaker.new(:yammer, notifier_class: notifier)
412
394
  10.times { circuit.run { 'success' }}
413
- assert @notifier.notified?, 'no notification sent'
414
- end
415
-
416
- def clear_notified!
417
- @notified = false
395
+ assert notifier.notified?, 'no notification sent'
418
396
  end
419
397
 
420
398
  def gimme_notifier(opts={})
421
- clear_notified!
422
- metric = opts.fetch(:metric,:error_rate)
399
+ metric = opts.fetch(:metric,:error_rate)
423
400
  metric_value = opts.fetch(:metric_value, 0.0)
424
- warning_msg = opts.fetch(:warning_msg, '')
401
+ warning_msg = opts.fetch(:warning_msg, '')
425
402
  fake_notifier = gimme
426
- give(fake_notifier).notify(:open) { @notified=true }
427
- give(fake_notifier).notify(:close) { @notified=true }
428
- give(fake_notifier).notify_warning(Gimme::Matchers::Anything.new) { @notified = true }
429
- give(fake_notifier).metric_gauge(metric, metric_value) { @notified=true }
403
+ notified = false
404
+ give(fake_notifier).notify(:open) { notified = true }
405
+ give(fake_notifier).notify(:close) { notified = true }
406
+ give(fake_notifier).notify_warning(Gimme::Matchers::Anything.new) { notified = true }
407
+ give(fake_notifier).metric_gauge(metric, metric_value) { notified = true }
430
408
  fake_notifier_class = gimme
431
409
  give(fake_notifier_class).new(:yammer,nil) { fake_notifier }
432
- give(fake_notifier_class).notified? { @notified }
410
+ give(fake_notifier_class).notified? { notified }
411
+ give(fake_notifier_class).clear_notified! { notified = false }
433
412
  fake_notifier_class
434
413
  end
435
414
  end
@@ -443,7 +422,7 @@ class CircuitBreakerTest < Minitest::Test
443
422
  response_value
444
423
  end
445
424
  end
446
- rescue RequestFailureError
425
+ rescue Timeout::Error
447
426
  nil
448
427
  end
449
428
  end
@@ -1,54 +1,45 @@
1
1
  require 'test_helper'
2
2
 
3
- class Circuitbox::ExampleStore < ActiveSupport::Cache::MemoryStore; end
3
+ class CircuitboxTest < Minitest::Test
4
4
 
5
- describe Circuitbox do
6
- before { Circuitbox.reset }
7
- after { Circuitbox.reset }
8
-
9
- describe "Circuitbox.circuit_store" do
10
- it "is configurable" do
11
- example_store = Circuitbox::ExampleStore.new
12
- Circuitbox.circuit_store = example_store
13
- assert_equal example_store, Circuitbox[:yammer].circuit_store
14
- end
5
+ def setup
6
+ Circuitbox.reset
15
7
  end
16
8
 
17
- describe "Circuitbox[:service]" do
18
- it "delegates to #circuit" do
19
- Circuitbox.expects(:circuit).with(:yammer, {})
20
- Circuitbox[:yammer]
21
- end
22
-
23
- it "creates a CircuitBreaker instance" do
24
- assert Circuitbox[:yammer].is_a? Circuitbox::CircuitBreaker
25
- end
9
+ def test_circuit_store_is_configurable
10
+ store = Moneta.new(:Memory, expires: true)
11
+ Circuitbox.circuit_store = store
12
+ assert_equal store, Circuitbox[:yammer].circuit_store
26
13
  end
27
14
 
28
- describe "#circuit" do
29
- it "returns the same circuit every time" do
30
- assert_equal Circuitbox.circuit(:yammer).object_id, Circuitbox.circuit(:yammer).object_id
31
- end
15
+ def test_delegates_to_circuit
16
+ Circuitbox.expects(:circuit).with(:yammer, {})
17
+ Circuitbox[:yammer]
18
+ end
32
19
 
33
- it "sets the circuit options the first time" do
34
- circuit_one = Circuitbox.circuit(:yammer, :sleep_window => 1337)
35
- circuit_two = Circuitbox.circuit(:yammer, :sleep_window => 2000)
20
+ def test_creates_a_circuit_breaker
21
+ assert Circuitbox[:yammer].is_a? Circuitbox::CircuitBreaker
22
+ end
36
23
 
37
- assert_equal 1337, circuit_one.option_value(:sleep_window)
38
- assert_equal 1337, circuit_two.option_value(:sleep_window)
39
- end
24
+ def test_returns_the_same_circuit_every_time
25
+ assert_equal Circuitbox.circuit(:yammer), Circuitbox.circuit(:yammer)
40
26
  end
41
27
 
42
- describe "#parameter_to_service_name" do
43
- it "parses out a service name from URI" do
44
- service = Circuitbox.parameter_to_service_name("http://api.yammer.com/api/v1/messages")
45
- assert_equal "api.yammer.com", service
46
- end
28
+ def test_sets_the_circuit_options_the_first_time_only
29
+ circuit_one = Circuitbox.circuit(:yammer, :sleep_window => 1337)
30
+ circuit_two = Circuitbox.circuit(:yammer, :sleep_window => 2000)
47
31
 
48
- it "uses the parameter as the service name if the parameter is not an URI" do
49
- service = Circuitbox.parameter_to_service_name(:yammer)
50
- assert_equal "yammer", service
51
- end
32
+ assert_equal 1337, circuit_one.option_value(:sleep_window)
33
+ assert_equal 1337, circuit_two.option_value(:sleep_window)
34
+ end
35
+
36
+ def test_uses_parsed_uri_host_as_identifier_for_circuit
37
+ service = Circuitbox.parameter_to_service_name("http://api.yammer.com/api/v1/messages")
38
+ assert_equal "api.yammer.com", service
52
39
  end
53
40
 
41
+ def test_uses_identifier_directly_for_circuit_if_it_is_not_an_uri
42
+ service = Circuitbox.parameter_to_service_name(:yammer)
43
+ assert_equal "yammer", service
44
+ end
54
45
  end
@@ -2,20 +2,20 @@ require 'test_helper'
2
2
  require 'circuitbox/notifier'
3
3
  require 'active_support/notifications'
4
4
 
5
- describe Circuitbox::Notifier do
6
- it "[notify] sends an ActiveSupport::Notification" do
5
+
6
+ class NotifierTest < Minitest::Test
7
+ def test_sends_notification_on_notify
7
8
  ActiveSupport::Notifications.expects(:instrument).with("circuit_open", circuit: 'yammer:12')
8
9
  Circuitbox::Notifier.new(:yammer, 12).notify(:open)
9
10
  end
10
11
 
11
- it "[notify_warning] sends an ActiveSupport::Notification" do
12
+ def test_sends_warning_notificaiton_notify_warning
12
13
  ActiveSupport::Notifications.expects(:instrument).with("circuit_warning", { circuit: 'yammer:12', message: 'hello'})
13
14
  Circuitbox::Notifier.new(:yammer, 12).notify_warning('hello')
14
15
  end
15
16
 
16
- it '[gauge] sends an ActiveSupport::Notifier' do
17
+ def test_sends_metric_as_notification
17
18
  ActiveSupport::Notifications.expects(:instrument).with("circuit_gauge", { circuit: 'yammer:12', gauge: 'ratio', value: 12})
18
19
  Circuitbox::Notifier.new(:yammer, 12).metric_gauge(:ratio, 12)
19
-
20
20
  end
21
21
  end
@@ -1,30 +1,23 @@
1
1
  require 'test_helper'
2
2
 
3
- describe Circuitbox::ServiceFailureError do
3
+ class ServiceFailureErrorTest < Minitest::Test
4
4
  class SomeOtherError < StandardError; end;
5
5
 
6
6
  attr_reader :error
7
7
 
8
- before do
9
- begin
10
- raise SomeOtherError, "some other error"
11
- rescue => ex
12
- @error = ex
13
- end
8
+ def setup
9
+ raise SomeOtherError, "some other error"
10
+ rescue => ex
11
+ @error = ex
14
12
  end
15
13
 
16
- describe '#to_s' do
17
- it 'includes message for wrapped exception' do
18
- ex = Circuitbox::ServiceFailureError.new('test', error)
19
- assert_equal "Circuitbox::ServiceFailureError wrapped: #{error}", ex.to_s
20
- end
14
+ def test_includes_the_message_of_the_wrapped_exception
15
+ ex = Circuitbox::ServiceFailureError.new('test', error)
16
+ assert_equal "Circuitbox::ServiceFailureError wrapped: #{error}", ex.to_s
21
17
  end
22
18
 
23
- describe '#backtrace' do
24
- it 'keeps the original exception backtrace' do
25
- ex = Circuitbox::ServiceFailureError.new('test', error)
26
- assert_equal error.backtrace, ex.backtrace
27
- end
19
+ def test_keeps_the_original_backtrace
20
+ ex = Circuitbox::ServiceFailureError.new('test', error)
21
+ assert_equal error.backtrace, ex.backtrace
28
22
  end
29
-
30
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: circuitbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fahim Ferdous
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-19 00:00:00.000000000 Z
11
+ date: 2016-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -290,7 +290,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
290
290
  version: '0'
291
291
  requirements: []
292
292
  rubyforge_project:
293
- rubygems_version: 2.4.3
293
+ rubygems_version: 2.4.8
294
294
  signing_key:
295
295
  specification_version: 4
296
296
  summary: A robust circuit breaker that manages failing external services.