circuitbox 1.1.1 → 2.0.0.pre4

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