circuitbox 1.1.1 → 2.0.0.pre4

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.
Files changed (37) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +53 -187
  3. data/lib/circuitbox/circuit_breaker/logger_messages.rb +31 -0
  4. data/lib/circuitbox/circuit_breaker.rb +134 -154
  5. data/lib/circuitbox/configuration.rb +51 -0
  6. data/lib/circuitbox/errors/error.rb +3 -2
  7. data/lib/circuitbox/errors/open_circuit_error.rb +3 -1
  8. data/lib/circuitbox/errors/service_failure_error.rb +5 -1
  9. data/lib/circuitbox/excon_middleware.rb +23 -30
  10. data/lib/circuitbox/faraday_middleware.rb +43 -63
  11. data/lib/circuitbox/memory_store/container.rb +30 -0
  12. data/lib/circuitbox/memory_store/monotonic_time.rb +13 -0
  13. data/lib/circuitbox/memory_store.rb +85 -0
  14. data/lib/circuitbox/notifier/active_support.rb +19 -0
  15. data/lib/circuitbox/notifier/null.rb +13 -0
  16. data/lib/circuitbox/timer.rb +51 -0
  17. data/lib/circuitbox/version.rb +3 -1
  18. data/lib/circuitbox.rb +14 -54
  19. metadata +106 -117
  20. data/.gitignore +0 -20
  21. data/.ruby-version +0 -1
  22. data/.travis.yml +0 -9
  23. data/Gemfile +0 -6
  24. data/Rakefile +0 -30
  25. data/benchmark/circuit_store_benchmark.rb +0 -114
  26. data/circuitbox.gemspec +0 -48
  27. data/lib/circuitbox/notifier.rb +0 -34
  28. data/test/circuit_breaker_test.rb +0 -436
  29. data/test/circuitbox_test.rb +0 -45
  30. data/test/excon_middleware_test.rb +0 -131
  31. data/test/faraday_middleware_test.rb +0 -175
  32. data/test/integration/circuitbox_cross_process_open_test.rb +0 -56
  33. data/test/integration/faraday_middleware_test.rb +0 -78
  34. data/test/integration_helper.rb +0 -48
  35. data/test/notifier_test.rb +0 -21
  36. data/test/service_failure_error_test.rb +0 -23
  37. data/test/test_helper.rb +0 -15
@@ -1,436 +0,0 @@
1
- require 'test_helper'
2
-
3
- class CircuitBreakerTest < Minitest::Test
4
- class ConnectionError < StandardError; end;
5
-
6
- def setup
7
- Circuitbox::CircuitBreaker.reset
8
- end
9
-
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)
13
- end
14
-
15
- def test_goes_into_half_open_state_on_sleep
16
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
17
- circuit.send(:open!)
18
- assert circuit.send(:half_open?)
19
- end
20
-
21
- class Ratio < Minitest::Test
22
- def setup
23
- Circuitbox::CircuitBreaker.reset
24
- @circuit = Circuitbox::CircuitBreaker.new(:yammer,
25
- sleep_window: 300,
26
- volume_threshold: 5,
27
- error_threshold: 33,
28
- timeout_seconds: 1)
29
- end
30
-
31
- def test_open_circuit_on_100_percent_failure
32
- run_counter = 0
33
- 10.times do
34
- @circuit.run do
35
- run_counter += 1
36
- raise Timeout::Error
37
- end
38
- end
39
- assert_equal 6, run_counter, 'the circuit did not open after 6 failures (5 failures + 10%)'
40
- end
41
-
42
- def test_keep_circuit_closed_on_success
43
- run_counter = 0
44
- 10.times do
45
- @circuit.run do
46
- run_counter += 1
47
- 'sucess'
48
- end
49
- end
50
- assert_equal 10, run_counter, 'run block was not executed 10 times'
51
- end
52
-
53
- def test_open_circuit_on_low_success_rate_below_limit
54
- run_counter = 0
55
- 5.times do
56
- @circuit.run do
57
- run_counter += 1
58
- raise Timeout::Error
59
- end
60
- end
61
-
62
- # one success
63
- @circuit.run { 'success'}
64
- assert_equal 5, @circuit.failure_count, 'the total count of failures is not 5'
65
-
66
- 5.times do
67
- @circuit.run do
68
- run_counter += 1
69
- raise Timeout::Error
70
- end
71
- end
72
- assert_equal 5, run_counter, 'the circuit did not open after 5 failures (5 failures + 10%)'
73
- end
74
-
75
- def test_keep_circuit_closed_on_low_failure_rate_below_failure_limit
76
- run_counter = 0
77
- 7.times do
78
- @circuit.run do
79
- run_counter += 1
80
- 'sucess'
81
- end
82
- end
83
- assert_equal 0, @circuit.failure_count, 'some errors were counted'
84
-
85
- 3.times do
86
- @circuit.run do
87
- run_counter += 1
88
- raise Timeout::Error
89
- end
90
- end
91
- assert_equal 10, run_counter, 'block was not executed 10 times'
92
- assert @circuit.error_rate < 33, 'error_rate pass over 33%'
93
- end
94
-
95
- def test_open_circuit_on_high_failure_rate_exceeding_failure_limit
96
- run_counter = 0
97
- 10.times do
98
- @circuit.run do
99
- run_counter += 1
100
- 'sucess'
101
- end
102
- end
103
- assert_equal 0, @circuit.failure_count, 'some errors were counted'
104
-
105
- 10.times do
106
- @circuit.run do
107
- run_counter += 1
108
- raise Timeout::Error
109
- end
110
- end
111
- # 5 failure on 15 run is 33%
112
- assert_equal 15, run_counter, 'block was not executed 10 times'
113
- assert @circuit.error_rate >= 33, 'error_rate pass over 33%'
114
- end
115
- end
116
-
117
- class Exceptions < Minitest::Test
118
- class SentinalError < StandardError; end
119
-
120
- def setup
121
- Circuitbox::CircuitBreaker.reset
122
- @circuit = Circuitbox::CircuitBreaker.new(:yammer, exceptions: [SentinalError])
123
- end
124
-
125
- def test_raises_when_circuit_is_open
126
- @circuit.stubs(open_flag?: true)
127
- assert_raises(Circuitbox::OpenCircuitError) { @circuit.run! {} }
128
- end
129
-
130
- def test_raises_on_service_failure
131
- assert_raises(Circuitbox::ServiceFailureError) { @circuit.run! { raise SentinalError } }
132
- end
133
-
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
138
- end
139
- end
140
-
141
- class CloseAfterSleep < Minitest::Test
142
- def setup
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)
150
- end
151
-
152
- def test_circuit_closes_after_sleep_time_window
153
- open_circuit!
154
- run_count = 0
155
- @circuit.run { run_count += 1 }
156
- assert_equal 0, run_count, 'circuit has not opened prior'
157
- # it is + 2 on purpose, because + 1 is flaky here
158
- sleep @circuit.option_value(:sleep_window) + 2
159
-
160
- @circuit.run { run_count += 1 }
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 } }
166
- end
167
- end
168
-
169
- class HalfOpenState < Minitest::Test
170
- def setup
171
- Circuitbox::CircuitBreaker.reset
172
- @circuit = Circuitbox::CircuitBreaker.new(:yammer)
173
- end
174
-
175
- def test_when_in_half_open_state_circuit_opens_on_failure
176
- @circuit.stubs(half_open?: true)
177
- @circuit.expects(:open!)
178
- @circuit.run { raise Timeout::Error }
179
- end
180
-
181
- def test_when_in_half_open_state_circuit_closes_on_success
182
- @circuit.send(:half_open!)
183
- @circuit.run { 'success' }
184
- refute @circuit.send(:half_open?)
185
- refute @circuit.send(:open?)
186
- end
187
- end
188
-
189
- def test_should_use_timeout_class_if_exceptions_are_not_defined
190
- circuit = Circuitbox::CircuitBreaker.new(:yammer, timeout_seconds: 45)
191
- circuit.expects(:timeout).with(45).once
192
- emulate_circuit_run(circuit, :success, StandardError)
193
- end
194
-
195
- def test_should_not_use_timeout_class_if_custom_exceptions_are_defined
196
- circuit = Circuitbox::CircuitBreaker.new(:yammer, exceptions: [ConnectionError])
197
- circuit.expects(:timeout).never
198
- emulate_circuit_run(circuit, :success, StandardError)
199
- end
200
-
201
- def test_should_return_response_if_it_doesnt_timeout
202
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
203
- response = emulate_circuit_run(circuit, :success, "success")
204
- assert_equal "success", response
205
- end
206
-
207
- def test_timeout_seconds_run_options_overrides_circuit_options
208
- circuit = Circuitbox::CircuitBreaker.new(:yammer, timeout_seconds: 60)
209
- circuit.expects(:timeout).with(30).once
210
- circuit.run(timeout_seconds: 30) { true }
211
- end
212
-
213
- def test_catches_connection_error_failures_if_defined
214
- circuit = Circuitbox::CircuitBreaker.new(:yammer, :exceptions => [ConnectionError])
215
- response = emulate_circuit_run(circuit, :failure, ConnectionError)
216
- assert_equal nil, response
217
- end
218
-
219
- def test_doesnt_catch_out_of_scope_exceptions
220
- sentinal = Class.new(StandardError)
221
- circuit = Circuitbox::CircuitBreaker.new(:yammer, :exceptions => [ConnectionError, Timeout::Error])
222
-
223
- assert_raises(sentinal) do
224
- emulate_circuit_run(circuit, :failure, sentinal)
225
- end
226
- end
227
-
228
- def test_records_response_failure
229
- circuit = Circuitbox::CircuitBreaker.new(:yammer, :exceptions => [Timeout::Error])
230
- circuit.expects(:log_event).with(:failure)
231
- emulate_circuit_run(circuit, :failure, Timeout::Error)
232
- end
233
-
234
- def test_records_response_skipped
235
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
236
- circuit.stubs(:open? => true)
237
- circuit.stubs(:log_event)
238
- circuit.expects(:log_event).with(:skipped)
239
- emulate_circuit_run(circuit, :failure, Timeout::Error)
240
- end
241
-
242
- def test_records_response_success
243
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
244
- circuit.expects(:log_event).with(:success)
245
- emulate_circuit_run(circuit, :success, "success")
246
- end
247
-
248
- def test_does_not_send_request_if_circuit_is_open
249
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
250
- circuit.stubs(:open? => true)
251
- circuit.expects(:yield).never
252
- response = emulate_circuit_run(circuit, :failure, Timeout::Error)
253
- assert_equal nil, response
254
- end
255
-
256
- def test_returns_nil_response_on_failed_request
257
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
258
- response = emulate_circuit_run(circuit, :failure, Timeout::Error)
259
- assert_equal nil, response
260
- end
261
-
262
- def test_puts_circuit_to_sleep_once_opened
263
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
264
- circuit.stubs(:open? => true)
265
-
266
- assert !circuit.send(:open_flag?)
267
- emulate_circuit_run(circuit, :failure, Timeout::Error)
268
- assert circuit.send(:open_flag?)
269
-
270
- circuit.expects(:open!).never
271
- emulate_circuit_run(circuit, :failure, Timeout::Error)
272
- end
273
-
274
- def test_open_is_true_if_open_flag
275
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
276
- circuit.stubs(:open_flag? => true)
277
- assert circuit.open?
278
- end
279
-
280
- def test_open_checks_if_volume_threshold_has_passed
281
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
282
- circuit.stubs(:open_flag? => false)
283
-
284
- circuit.expects(:passed_volume_threshold?).once
285
- circuit.open?
286
- end
287
-
288
- def test_open_checks_error_rate_threshold
289
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
290
- circuit.stubs(:open_flag? => false,
291
- :passed_volume_threshold? => true)
292
-
293
- circuit.expects(:passed_rate_threshold?).once
294
- circuit.open?
295
- end
296
-
297
- def test_open_is_false_if_awake_and_under_rate_threshold
298
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
299
- circuit.stubs(:open_flag? => false,
300
- :passed_volume_threshold? => false,
301
- :passed_rate_threshold => false)
302
-
303
- assert !circuit.open?
304
- end
305
-
306
- def test_error_rate_threshold_calculation
307
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
308
- circuit.stubs(:failure_count => 3, :success_count => 2)
309
- assert circuit.send(:passed_rate_threshold?)
310
-
311
- circuit.stubs(:failure_count => 2, :success_count => 3)
312
- assert !circuit.send(:passed_rate_threshold?)
313
- end
314
-
315
- def test_logs_and_retrieves_success_events
316
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
317
- 5.times { circuit.send(:log_event, :success) }
318
- assert_equal 5, circuit.send(:success_count)
319
- end
320
-
321
- def test_logs_and_retrieves_failure_events
322
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
323
- 5.times { circuit.send(:log_event, :failure) }
324
- assert_equal 5, circuit.send(:failure_count)
325
- end
326
-
327
- def test_logs_events_by_minute
328
- circuit = Circuitbox::CircuitBreaker.new(:yammer)
329
-
330
- Timecop.travel(Time.now.change(sec: 5))
331
- 4.times { circuit.send(:log_event, :success) }
332
- assert_equal 4, circuit.send(:success_count)
333
-
334
- Timecop.travel(1.minute.from_now)
335
- 7.times { circuit.send(:log_event, :success) }
336
- assert_equal 7, circuit.send(:success_count)
337
-
338
- Timecop.travel(30.seconds.from_now)
339
- circuit.send(:log_event, :success)
340
- assert_equal 8, circuit.send(:success_count)
341
-
342
- Timecop.travel(50.seconds.from_now)
343
- assert_equal 0, circuit.send(:success_count)
344
- end
345
-
346
- class Notifications < Minitest::Test
347
- def setup
348
- Circuitbox::CircuitBreaker.reset
349
- end
350
-
351
- def test_notification_on_open
352
- notifier = gimme_notifier
353
- circuit = Circuitbox::CircuitBreaker.new(:yammer, notifier_class: notifier)
354
- 10.times { circuit.run { raise Timeout::Error }}
355
- assert notifier.notified?, 'no notification sent'
356
- end
357
-
358
- def test_notification_on_close
359
- notifier = gimme_notifier
360
- circuit = Circuitbox::CircuitBreaker.new(:yammer, notifier_class: notifier)
361
- 5.times { circuit.run { raise Timeout::Error }}
362
- notifier.clear_notified!
363
- 10.times { circuit.run { 'success' }}
364
- assert notifier.notified?, 'no notification sent'
365
- end
366
-
367
- def test_warning_when_sleep_window_is_shorter_than_time_window
368
- notifier = gimme_notifier
369
- Circuitbox::CircuitBreaker.new(:yammer,
370
- notifier_class: notifier,
371
- sleep_window: 1,
372
- time_window: 10)
373
- assert notifier.notified?, 'no notification sent'
374
- end
375
-
376
- def test_does_not_warn_on_sleep_window_being_correctly_sized
377
- notifier = gimme_notifier
378
- Circuitbox::CircuitBreaker.new(:yammer,
379
- notifier_class: notifier,
380
- sleep_window: 11,
381
- time_window: 10)
382
- assert_equal false, notifier.notified?, 'no notification sent'
383
- end
384
-
385
- def test_notifies_on_success_rate_calculation
386
- notifier = gimme_notifier(metric: :error_rate, metric_value: 0.0)
387
- circuit = Circuitbox::CircuitBreaker.new(:yammer, notifier_class: notifier)
388
- 10.times { circuit.run { "success" } }
389
- assert notifier.notified?, "no notification sent"
390
- end
391
-
392
- def test_notifies_on_error_rate_calculation
393
- notifier = gimme_notifier(metric: :failure_count, metric_value: 1)
394
- circuit = Circuitbox::CircuitBreaker.new(:yammer, notifier_class: notifier)
395
- 10.times { circuit.run { raise Timeout::Error }}
396
- assert notifier.notified?, 'no notification sent'
397
- end
398
-
399
- def test_success_count_on_error_rate_calculation
400
- notifier = gimme_notifier(metric: :success_count, metric_value: 6)
401
- circuit = Circuitbox::CircuitBreaker.new(:yammer, notifier_class: notifier)
402
- 10.times { circuit.run { 'success' }}
403
- assert notifier.notified?, 'no notification sent'
404
- end
405
-
406
- def gimme_notifier(opts={})
407
- metric = opts.fetch(:metric,:error_rate)
408
- metric_value = opts.fetch(:metric_value, 0.0)
409
- warning_msg = opts.fetch(:warning_msg, '')
410
- fake_notifier = gimme
411
- notified = false
412
- give(fake_notifier).notify(:open) { notified = true }
413
- give(fake_notifier).notify(:close) { notified = true }
414
- give(fake_notifier).notify_warning(Gimme::Matchers::Anything.new) { notified = true }
415
- give(fake_notifier).metric_gauge(metric, metric_value) { notified = true }
416
- fake_notifier_class = gimme
417
- give(fake_notifier_class).new(:yammer,nil) { fake_notifier }
418
- give(fake_notifier_class).notified? { notified }
419
- give(fake_notifier_class).clear_notified! { notified = false }
420
- fake_notifier_class
421
- end
422
- end
423
-
424
- def emulate_circuit_run(circuit, response_type, response_value)
425
- circuit.run do
426
- case response_type
427
- when :failure
428
- raise response_value
429
- when :success
430
- response_value
431
- end
432
- end
433
- rescue Timeout::Error
434
- nil
435
- end
436
- end
@@ -1,45 +0,0 @@
1
- require 'test_helper'
2
-
3
- class CircuitboxTest < Minitest::Test
4
-
5
- def setup
6
- Circuitbox.reset
7
- end
8
-
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
13
- end
14
-
15
- def test_delegates_to_circuit
16
- Circuitbox.expects(:circuit).with(:yammer, {})
17
- Circuitbox[:yammer]
18
- end
19
-
20
- def test_creates_a_circuit_breaker
21
- assert Circuitbox[:yammer].is_a? Circuitbox::CircuitBreaker
22
- end
23
-
24
- def test_returns_the_same_circuit_every_time
25
- assert_equal Circuitbox.circuit(:yammer), Circuitbox.circuit(:yammer)
26
- end
27
-
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)
31
-
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
39
- end
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
45
- end
@@ -1,131 +0,0 @@
1
- require 'test_helper'
2
- require 'circuitbox/excon_middleware'
3
-
4
- class SentialException < StandardError; end
5
-
6
- class Circuitbox
7
- class ExconMiddlewareTest < Minitest::Test
8
-
9
- attr_reader :app
10
-
11
- def setup
12
- @app = gimme
13
- end
14
-
15
- def test_default_identifier
16
- env = { path: "sential" }
17
- assert_equal "sential", ExconMiddleware.new(app).identifier.call(env)
18
- end
19
-
20
- def test_overwrite_identifier
21
- middleware = ExconMiddleware.new(app, identifier: "sential")
22
- assert_equal middleware.identifier, "sential"
23
- end
24
-
25
- def test_overwrite_default_value_generator_lambda
26
- stub_circuitbox
27
- env = { path: "path" }
28
- give(circuitbox).circuit("path", anything) { circuit }
29
- give(circuit).run!(anything) { raise Circuitbox::Error }
30
- default_value_generator = lambda { |_, _| :sential }
31
- middleware = ExconMiddleware.new(app,
32
- circuitbox: circuitbox,
33
- default_value: default_value_generator)
34
- assert_equal :sential, middleware.error_call(env)
35
- end
36
-
37
- def test_overwrite_default_value_generator_static_value
38
- stub_circuitbox
39
- env = { path: "path" }
40
- give(circuitbox).circuit("path", anything) { circuit }
41
- give(circuit).run!(anything) { raise Circuitbox::Error }
42
- middleware = ExconMiddleware.new(app, circuitbox: circuitbox, default_value: :sential)
43
- assert_equal :sential, middleware.error_call(env)
44
- end
45
-
46
- def test_default_exceptions
47
- middleware = ExconMiddleware.new(app)
48
- assert_includes middleware.exceptions, Excon::Errors::Timeout
49
- assert_includes middleware.exceptions, ExconMiddleware::RequestFailed
50
- end
51
-
52
- def test_overridde_success_response
53
- env = { path: "path", response: { status: 400 } }
54
- error_response = lambda { |r| r[:status] >= 500 }
55
- give(app).response_call(anything) { Excon::Response.new(status: 400) }
56
- mw = ExconMiddleware.new(app, open_circuit: error_response)
57
- response = mw.response_call(env)
58
- assert_kind_of Excon::Response, response
59
- assert_equal response.status, 400
60
- end
61
-
62
- def test_default_success_response
63
- env = { path: "path", response: { status: 400 } }
64
- app = gimme
65
- give(app).response_call(anything) { Excon::Response.new(status: 400) }
66
- response = nil
67
-
68
- mw = ExconMiddleware.new(app)
69
- response = mw.response_call(env)
70
-
71
- assert_kind_of Excon::Response, response
72
- assert_equal response.status, 503
73
- end
74
-
75
- def test_overwrite_exceptions
76
- middleware = ExconMiddleware.new(app, exceptions: [SentialException])
77
- assert_includes middleware.exceptions, SentialException
78
- end
79
-
80
- def test_pass_circuit_breaker_run_options
81
- stub_circuitbox
82
- give(circuit).run!(:sential)
83
- give(circuitbox).circuit("path", anything) { circuit }
84
- env = { path: "path", circuit_breaker_run_options: :sential }
85
- middleware = ExconMiddleware.new(app, circuitbox: circuitbox)
86
- middleware.request_call(env)
87
- verify(circuit, 1.times).run!(:sential)
88
- end
89
-
90
- def test_pass_circuit_breaker_options
91
- stub_circuitbox
92
- env = { path: "path" }
93
- expected_circuit_breaker_options = {
94
- sential: :sential,
95
- exceptions: ExconMiddleware::DEFAULT_EXCEPTIONS
96
- }
97
- give(circuitbox).circuit("path", expected_circuit_breaker_options) { circuit }
98
- options = { circuitbox: circuitbox, circuit_breaker_options: { sential: :sential } }
99
- middleware = ExconMiddleware.new(app, options)
100
- middleware.request_call(env)
101
-
102
- verify(circuitbox, 1.times).circuit("path", expected_circuit_breaker_options)
103
- end
104
-
105
- def test_overwrite_circuitbreaker_default_value
106
- stub_circuitbox
107
- env = { path: "path", circuit_breaker_default_value: :sential }
108
- give(circuitbox).circuit("path", anything) { circuit }
109
- give(circuit).run!(anything) { raise Circuitbox::Error }
110
- middleware = ExconMiddleware.new(app, circuitbox: circuitbox)
111
- assert_equal middleware.error_call(env), :sential
112
- end
113
-
114
- def test_return_null_response_for_open_circuit
115
- stub_circuitbox
116
- env = { path: "path" }
117
- give(circuit).run!(anything) { raise Circuitbox::Error }
118
- give(circuitbox).circuit("path", anything) { circuit }
119
- mw = ExconMiddleware.new(app, circuitbox: circuitbox)
120
- response = mw.error_call(env)
121
- assert_kind_of Excon::Response, response
122
- assert_equal response.status, 503
123
- end
124
-
125
- attr_reader :circuitbox, :circuit
126
- def stub_circuitbox
127
- @circuitbox = gimme
128
- @circuit = gimme
129
- end
130
- end
131
- end