circuitbox 1.0.3 → 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.
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.