right_support 2.10.1 → 2.11.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/right_support/data/token.rb +51 -0
- data/lib/right_support/data.rb +1 -0
- data/lib/right_support/net/lb/base.rb +96 -0
- data/lib/right_support/net/lb/health_check.rb +22 -46
- data/lib/right_support/net/lb/round_robin.rb +5 -23
- data/lib/right_support/net/lb/sticky.rb +10 -27
- data/lib/right_support/net/lb.rb +2 -1
- data/lib/right_support/net/request_balancer.rb +184 -60
- data/lib/right_support/rack/request_logger.rb +221 -42
- data/lib/right_support/rack/request_tracker.rb +112 -25
- data/right_support.gemspec +11 -6
- data/spec/data/token_spec.rb +21 -0
- data/spec/net/{balancing → lb}/health_check_spec.rb +56 -21
- data/spec/net/{balancing → lb}/round_robin_spec.rb +0 -0
- data/spec/net/{balancing/sticky_policy_spec.rb → lb/sticky_spec.rb} +1 -1
- data/spec/net/request_balancer_spec.rb +161 -57
- data/spec/rack/request_logger_spec.rb +91 -27
- data/spec/rack/request_tracker_spec.rb +111 -1
- metadata +8 -5
@@ -11,7 +11,8 @@ describe RightSupport::Net::LB::HealthCheck do
|
|
11
11
|
@reset_time = 60
|
12
12
|
@policy = RightSupport::Net::LB::HealthCheck.new(
|
13
13
|
:yellow_states => @yellow_states,
|
14
|
-
:reset_time => @reset_time
|
14
|
+
:reset_time => @reset_time,
|
15
|
+
:health_check => lambda { |ep| true })
|
15
16
|
@policy.set_endpoints(@endpoints)
|
16
17
|
@trials = 2500
|
17
18
|
end
|
@@ -67,9 +68,11 @@ describe RightSupport::Net::LB::HealthCheck do
|
|
67
68
|
before(:each) do
|
68
69
|
@yellow_states = 3
|
69
70
|
@health_updates = []
|
70
|
-
@policy = RightSupport::Net::LB::HealthCheck.new(
|
71
|
-
|
72
|
-
|
71
|
+
@policy = RightSupport::Net::LB::HealthCheck.new(
|
72
|
+
:yellow_states => @yellow_states,
|
73
|
+
:reset_time => @reset_time,
|
74
|
+
:on_health_change => lambda { |health| @health_updates << health },
|
75
|
+
:health_check => lambda { |ep| true })
|
73
76
|
@policy.set_endpoints(@endpoints)
|
74
77
|
|
75
78
|
# put everyone into green state, then forget all health updates. this helps us write an
|
@@ -157,9 +160,10 @@ describe RightSupport::Net::LB::HealthCheck do
|
|
157
160
|
before(:each) do
|
158
161
|
@yellow_states = 3
|
159
162
|
@health_updates = []
|
160
|
-
@policy = RightSupport::Net::LB::HealthCheck.new(
|
161
|
-
|
162
|
-
|
163
|
+
@policy = RightSupport::Net::LB::HealthCheck.new(
|
164
|
+
:yellow_states => @yellow_states, :reset_time => @reset_time,
|
165
|
+
:on_health_change => lambda { |health| @health_updates << health },
|
166
|
+
:health_check => lambda { |ep| true })
|
163
167
|
@policy.set_endpoints(@endpoints)
|
164
168
|
|
165
169
|
# put everyone into green state, then forget all health updates. this helps us write an
|
@@ -212,7 +216,7 @@ describe RightSupport::Net::LB::HealthCheck do
|
|
212
216
|
@yellow_states.times { @policy.bad(@red, 0, Time.now) }
|
213
217
|
@policy.should have_red_endpoint(@red)
|
214
218
|
|
215
|
-
seen = find_empirical_distribution(@trials,@endpoints) do
|
219
|
+
seen = find_empirical_distribution(@trials,@endpoints) do
|
216
220
|
@policy.next
|
217
221
|
end
|
218
222
|
|
@@ -232,24 +236,53 @@ describe RightSupport::Net::LB::HealthCheck do
|
|
232
236
|
should_be_chosen_fairly(seen, @trials, @endpoints.size - 1)
|
233
237
|
end
|
234
238
|
|
235
|
-
it
|
236
|
-
|
237
|
-
|
239
|
+
it "eliminates bad endpoints during round robin selection" do
|
240
|
+
endpoints = [1, 2, 3, 4, 5]
|
241
|
+
policy = RightSupport::Net::LB::HealthCheck.new(
|
242
|
+
:yellow_states => 2,
|
243
|
+
:health_check => lambda { |ep| true })
|
244
|
+
policy.set_endpoints(endpoints)
|
245
|
+
policy.instance_variable_set(:@counter, 0)
|
246
|
+
breaking_bad = lambda { |ep| ep < 4 }
|
238
247
|
|
239
|
-
|
248
|
+
# first pass; initially all green, mark some yellow.
|
249
|
+
expected = [1, 2, 3, 4, 5]
|
240
250
|
actual = []
|
241
|
-
|
251
|
+
endpoints.size.times do
|
252
|
+
endpoint, need_health_check = policy.next
|
253
|
+
need_health_check.should be_false
|
254
|
+
if breaking_bad.call(endpoint)
|
255
|
+
policy.bad(endpoint, 0, Time.now) # go yellow
|
256
|
+
end
|
257
|
+
actual << endpoint
|
258
|
+
end
|
259
|
+
actual.should == expected
|
242
260
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
261
|
+
# second pass; some yellow, others green. yellows go red after being
|
262
|
+
# selected and are eliminated from subsequent round-robin selection.
|
263
|
+
expected = [1, 4, 5, 2, 3]
|
264
|
+
actual = []
|
247
265
|
endpoints.size.times do
|
248
|
-
endpoint,
|
249
|
-
|
266
|
+
endpoint, need_health_check = policy.next
|
267
|
+
if breaking_bad.call(endpoint)
|
268
|
+
# yellow is still viable but a health-check is requested.
|
269
|
+
need_health_check.should be_true
|
270
|
+
policy.bad(endpoint, 0, Time.now) # go red
|
271
|
+
else
|
272
|
+
need_health_check.should be_false
|
273
|
+
end
|
250
274
|
actual << endpoint
|
251
275
|
end
|
276
|
+
actual.should == expected
|
252
277
|
|
278
|
+
# third pass; green or red, no more yellow.
|
279
|
+
expected = [4, 5, 4, 5, 4]
|
280
|
+
actual = []
|
281
|
+
endpoints.size.times do
|
282
|
+
endpoint, need_health_check = policy.next
|
283
|
+
need_health_check.should be_false
|
284
|
+
actual << endpoint
|
285
|
+
end
|
253
286
|
actual.should == expected
|
254
287
|
end
|
255
288
|
end
|
@@ -350,8 +383,10 @@ describe RightSupport::Net::LB::HealthCheck do
|
|
350
383
|
context :set_endpoints do
|
351
384
|
context 'given endpoints stack does not exist' do
|
352
385
|
before(:each) do
|
353
|
-
@policy = RightSupport::Net::LB::HealthCheck.new(
|
354
|
-
|
386
|
+
@policy = RightSupport::Net::LB::HealthCheck.new(
|
387
|
+
:yellow_states => @yellow_states,
|
388
|
+
:reset_time => @reset_time,
|
389
|
+
:health_check => lambda { |ep| true })
|
355
390
|
end
|
356
391
|
|
357
392
|
it 'acts as initializer' do
|
File without changes
|
@@ -26,7 +26,7 @@ describe RightSupport::Net::LB::Sticky do
|
|
26
26
|
context 'given all servers are healthy' do
|
27
27
|
it 'sticks to chosen one' do
|
28
28
|
chance = 1.0
|
29
|
-
seen = find_empirical_distribution(@trials,@endpoints) do
|
29
|
+
seen = find_empirical_distribution(@trials,@endpoints) do
|
30
30
|
@policy.next
|
31
31
|
end
|
32
32
|
seen.each_pair do |_, count|
|
@@ -36,7 +36,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
36
36
|
|
37
37
|
exception = expect.first
|
38
38
|
count = expect.last
|
39
|
-
rb =
|
39
|
+
rb = described_class.new([1,2,3], :fatal=>fatal)
|
40
40
|
@tries = 0
|
41
41
|
|
42
42
|
code = lambda do
|
@@ -72,10 +72,11 @@ describe RightSupport::Net::RequestBalancer do
|
|
72
72
|
|
73
73
|
expect = number_of_endpoints
|
74
74
|
yellow_states = 4
|
75
|
-
rb =
|
76
|
-
|
77
|
-
|
78
|
-
|
75
|
+
rb = described_class.new(
|
76
|
+
(1..expect).to_a,
|
77
|
+
:policy => RightSupport::Net::LB::HealthCheck,
|
78
|
+
:health_check => test,
|
79
|
+
:yellow_states => yellow_states)
|
79
80
|
@health_checks = 0
|
80
81
|
tries = 0
|
81
82
|
l = lambda do
|
@@ -98,20 +99,25 @@ describe RightSupport::Net::RequestBalancer do
|
|
98
99
|
context :initialize do
|
99
100
|
it 'requires a list of endpoint URLs' do
|
100
101
|
lambda do
|
101
|
-
|
102
|
+
described_class.new(nil)
|
102
103
|
end.should raise_exception(ArgumentError)
|
103
104
|
end
|
104
105
|
|
105
106
|
context 'with Integer :retry option' do
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
107
|
+
[1, 2].each do |retry_value|
|
108
|
+
context "and :retry=#{retry_value}" do
|
109
|
+
it "stops after #{retry_value} total tries" do
|
110
|
+
lambda do
|
111
|
+
# note the legacy :retry integer value has no backoff.
|
112
|
+
@tries = 0
|
113
|
+
described_class.new([1, 2, 3], :retry => retry_value).request do |u|
|
114
|
+
@tries += 1
|
115
|
+
raise NoBigDeal
|
116
|
+
end
|
117
|
+
end.should raise_error
|
118
|
+
@tries.should == retry_value
|
112
119
|
end
|
113
|
-
end
|
114
|
-
@tries.should == 1
|
120
|
+
end
|
115
121
|
end
|
116
122
|
end
|
117
123
|
|
@@ -123,7 +129,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
123
129
|
@tries < 1
|
124
130
|
end
|
125
131
|
|
126
|
-
balancer =
|
132
|
+
balancer = described_class.new([1, 2, 3], :retry => proc)
|
127
133
|
lambda do
|
128
134
|
balancer.request do |u|
|
129
135
|
@tries += 1
|
@@ -133,12 +139,33 @@ describe RightSupport::Net::RequestBalancer do
|
|
133
139
|
|
134
140
|
@tries.should == 1
|
135
141
|
end
|
142
|
+
|
143
|
+
[1, 2].each do |max_attempts|
|
144
|
+
context "with backoff_retry_callback(#{max_attempts})" do
|
145
|
+
it "stops after #{max_attempts} total tries" do
|
146
|
+
start_time = ::Time.now
|
147
|
+
retry_proc = described_class.backoff_retry_callback(max_attempts)
|
148
|
+
lambda do
|
149
|
+
@tries = 0
|
150
|
+
described_class.new([1, 2, 3], :retry => retry_proc).request do |u|
|
151
|
+
@tries += 1
|
152
|
+
raise NoBigDeal
|
153
|
+
end
|
154
|
+
end.should raise_error
|
155
|
+
end_time = ::Time.now
|
156
|
+
@tries.should == max_attempts
|
157
|
+
if max_attempts == 2
|
158
|
+
((end_time - start_time) >= 2).should be_true # assert backoff
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
136
163
|
end
|
137
164
|
|
138
165
|
context ':fatal option' do
|
139
166
|
it 'has reasonable defaults' do
|
140
|
-
exceptions =
|
141
|
-
balancer =
|
167
|
+
exceptions = described_class::DEFAULT_FATAL_EXCEPTIONS - [SignalException]
|
168
|
+
balancer = described_class.new([1])
|
142
169
|
exceptions.each do |klass|
|
143
170
|
lambda do
|
144
171
|
balancer.request { |ep| raise klass }
|
@@ -150,13 +177,13 @@ describe RightSupport::Net::RequestBalancer do
|
|
150
177
|
it 'validates the arity' do
|
151
178
|
bad_lambda = lambda { |too, many, arguments| }
|
152
179
|
lambda do
|
153
|
-
|
180
|
+
described_class.new([1,2], :fatal=>bad_lambda)
|
154
181
|
end.should raise_error(ArgumentError)
|
155
182
|
end
|
156
183
|
|
157
184
|
it 'delegates to the Proc' do
|
158
185
|
always_retry = lambda { |e| false }
|
159
|
-
balancer =
|
186
|
+
balancer = described_class.new([1,2], :fatal=>always_retry)
|
160
187
|
|
161
188
|
lambda do
|
162
189
|
balancer.request do |ep|
|
@@ -174,7 +201,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
174
201
|
|
175
202
|
context 'with an Exception' do
|
176
203
|
it 'considers that class of Exception to be fatal' do
|
177
|
-
balancer =
|
204
|
+
balancer = described_class.new([1], :fatal=>BigDeal)
|
178
205
|
lambda do
|
179
206
|
balancer.request { |ep| raise BigDeal }
|
180
207
|
end.should raise_error(BigDeal)
|
@@ -184,7 +211,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
184
211
|
context 'with an Array' do
|
185
212
|
it 'considers any class in the array to be fatal' do
|
186
213
|
exceptions = [ArgumentError, BigDeal]
|
187
|
-
balancer =
|
214
|
+
balancer = described_class.new([1], :fatal=>exceptions)
|
188
215
|
exceptions.each do |klass|
|
189
216
|
lambda do
|
190
217
|
balancer.request { |ep| raise klass }
|
@@ -198,7 +225,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
198
225
|
it 'validates the arity' do
|
199
226
|
bad_lambda = lambda { |way, too, many, arguments| }
|
200
227
|
lambda do
|
201
|
-
|
228
|
+
described_class.new([1,2], :on_exception=>bad_lambda)
|
202
229
|
end.should raise_error(ArgumentError)
|
203
230
|
end
|
204
231
|
end
|
@@ -207,23 +234,23 @@ describe RightSupport::Net::RequestBalancer do
|
|
207
234
|
it 'accepts a Class' do
|
208
235
|
policy = RightSupport::Net::LB::RoundRobin
|
209
236
|
lambda {
|
210
|
-
|
237
|
+
described_class.new([1,2], :policy=>policy)
|
211
238
|
}.should_not raise_error
|
212
239
|
end
|
213
240
|
|
214
241
|
it 'accepts an object' do
|
215
242
|
policy = RightSupport::Net::LB::RoundRobin.new([1,2])
|
216
243
|
lambda {
|
217
|
-
|
244
|
+
described_class.new([1,2], :policy=>policy)
|
218
245
|
}.should_not raise_error
|
219
246
|
end
|
220
247
|
|
221
248
|
it 'checks for duck-type compatibility' do
|
222
249
|
lambda {
|
223
|
-
|
250
|
+
described_class.new([1,2], :policy=>String)
|
224
251
|
}.should raise_error
|
225
252
|
lambda {
|
226
|
-
|
253
|
+
described_class.new([1,2], :policy=>'I like cheese')
|
227
254
|
}.should raise_error
|
228
255
|
end
|
229
256
|
end
|
@@ -235,12 +262,12 @@ describe RightSupport::Net::RequestBalancer do
|
|
235
262
|
|
236
263
|
it 'accepts a block' do
|
237
264
|
lambda {
|
238
|
-
|
265
|
+
described_class.new([1,2], :health_check => @health_check)
|
239
266
|
}.should_not raise_error
|
240
267
|
end
|
241
268
|
|
242
269
|
it 'calls specified block' do
|
243
|
-
@balancer =
|
270
|
+
@balancer = described_class.new([1,2], :health_check => @health_check)
|
244
271
|
@options = @balancer.instance_variable_get("@options")
|
245
272
|
@options[:health_check].call(1).should be_eql("HealthCheck passed for 1!")
|
246
273
|
end
|
@@ -249,7 +276,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
249
276
|
|
250
277
|
context 'with default :health_check option' do
|
251
278
|
it 'calls default block' do
|
252
|
-
@balancer =
|
279
|
+
@balancer = described_class.new([1,2])
|
253
280
|
@options = @balancer.instance_variable_get("@options")
|
254
281
|
@options[:health_check].call(1).should be_true
|
255
282
|
end
|
@@ -263,7 +290,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
263
290
|
|
264
291
|
it 'accepts a block' do
|
265
292
|
lambda {
|
266
|
-
|
293
|
+
described_class.new([1,2], :on_health_change => @on_health_change)
|
267
294
|
}.should_not raise_error
|
268
295
|
end
|
269
296
|
end
|
@@ -272,7 +299,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
272
299
|
before(:each) do
|
273
300
|
flexmock(RightSupport::Net::DNS).should_receive(:resolve_with_hostnames).
|
274
301
|
with(['host1', 'host2']).and_return({'host1' => make_endpoint(['1.1.1.1', '2.2.2.2']), 'host2' => make_endpoint(['3.3.3.3'])})
|
275
|
-
@balancer =
|
302
|
+
@balancer = described_class.new(['host1', 'host2'], :resolve => 15)
|
276
303
|
end
|
277
304
|
|
278
305
|
it 'performs an initial resolution' do
|
@@ -291,26 +318,102 @@ describe RightSupport::Net::RequestBalancer do
|
|
291
318
|
context :request do
|
292
319
|
it 'requires a block' do
|
293
320
|
lambda do
|
294
|
-
|
321
|
+
described_class.new([1]).request
|
295
322
|
end.should raise_exception(ArgumentError)
|
296
323
|
end
|
297
324
|
|
298
|
-
|
299
|
-
list
|
325
|
+
context 'with a single thread' do
|
326
|
+
let(:list) { [1,2,3,4,5,6,7,8,9,10] }
|
327
|
+
|
328
|
+
subject { described_class.new(list) }
|
329
|
+
|
330
|
+
it 'retries until a request completes' do
|
331
|
+
queue = Queue.new
|
332
|
+
10.times do
|
333
|
+
x = subject.request do |l|
|
334
|
+
raise NoBigDeal, "Fall down go boom!" unless l == 5
|
335
|
+
l
|
336
|
+
end
|
337
|
+
x.should == 5
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
context 'with multiple threads and thread-safety enabled' do
|
343
|
+
let(:list) { [1,2,3,4,5,6,7,8,9,10] }
|
344
|
+
|
345
|
+
def boom(ep)
|
346
|
+
raise NoBigDeal, "Fall down go boom!" unless ep == 5
|
347
|
+
true
|
348
|
+
end
|
300
349
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
350
|
+
subject do
|
351
|
+
described_class.new(
|
352
|
+
list,
|
353
|
+
thread_safe: true,
|
354
|
+
policy: ::RightSupport::Net::LB::HealthCheck,
|
355
|
+
health_check: method(:boom))
|
356
|
+
end
|
357
|
+
|
358
|
+
it 'retries until a request completes' do
|
359
|
+
count = list.size * 3
|
360
|
+
expected_responses = nil
|
361
|
+
expected_stats = list.inject({}) do |h, ep|
|
362
|
+
begin
|
363
|
+
boom(ep)
|
364
|
+
h[ep] = 'green'
|
365
|
+
expected_responses = [ep] * count
|
366
|
+
rescue NoBigDeal
|
367
|
+
h[ep] = 'red'
|
368
|
+
end
|
369
|
+
h
|
305
370
|
end
|
306
371
|
|
307
|
-
|
372
|
+
queue = Queue.new
|
373
|
+
count.times do
|
374
|
+
::Thread.new do
|
375
|
+
stop_time = ::Time.now + 10
|
376
|
+
loop do
|
377
|
+
begin
|
378
|
+
x = subject.request do |ep|
|
379
|
+
boom(ep)
|
380
|
+
ep
|
381
|
+
end
|
382
|
+
queue.push(x)
|
383
|
+
break
|
384
|
+
rescue ::RightSupport::Net::NoResult => e
|
385
|
+
# this can happen with too much thread contention for failing
|
386
|
+
# endpoints. the issue is that other threads keep snaking the
|
387
|
+
# only good endpoint away from this thread (i.e. keep
|
388
|
+
# incrementing the counter in health-check policy) until the
|
389
|
+
# allowed number of retries is exhausted. only when the other
|
390
|
+
# threads die can we be sure of getting the only good endpoint.
|
391
|
+
#
|
392
|
+
# keep trying for the purpose of this test but do not allow
|
393
|
+
# infinite retries.
|
394
|
+
if ::Time.now >= stop_time
|
395
|
+
queue.push(e)
|
396
|
+
break
|
397
|
+
end
|
398
|
+
rescue ::Exception => e
|
399
|
+
queue.push(e)
|
400
|
+
break
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
actual_responses = []
|
406
|
+
count.times do
|
407
|
+
actual_responses << queue.pop
|
408
|
+
end
|
409
|
+
actual_responses.should == expected_responses
|
410
|
+
subject.get_stats.should == expected_stats
|
308
411
|
end
|
309
412
|
end
|
310
413
|
|
311
414
|
it 'raises if no request completes' do
|
312
415
|
lambda do
|
313
|
-
|
416
|
+
described_class.request([1,2,3]) do |l|
|
314
417
|
raise NoBigDeal, "Fall down go boom!"
|
315
418
|
end
|
316
419
|
end.should raise_exception(RightSupport::Net::NoResult, /NoBigDeal/)
|
@@ -349,7 +452,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
349
452
|
context 'with default :fatal option' do
|
350
453
|
it 'retries most Ruby builtin errors' do
|
351
454
|
list = [1,2,3,4,5,6,7,8,9,10]
|
352
|
-
rb =
|
455
|
+
rb = described_class.new(list)
|
353
456
|
|
354
457
|
[IOError, SystemCallError, SocketError].each do |klass|
|
355
458
|
test_raise(nil, klass, [RightSupport::Net::NoResult, 3])
|
@@ -358,7 +461,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
358
461
|
|
359
462
|
it 'does not retry program errors' do
|
360
463
|
list = [1,2,3,4,5,6,7,8,9,10]
|
361
|
-
rb =
|
464
|
+
rb = described_class.new(list)
|
362
465
|
|
363
466
|
[ArgumentError, LoadError, NameError].each do |klass|
|
364
467
|
test_raise(nil, klass, [klass, 1])
|
@@ -372,7 +475,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
372
475
|
|
373
476
|
it 'does not retry HTTP 4xx other than timeout' do
|
374
477
|
list = [1,2,3,4,5,6,7,8,9,10]
|
375
|
-
rb =
|
478
|
+
rb = described_class.new(list)
|
376
479
|
|
377
480
|
codes = [401, 402, 403, 404, 405, 406, 407, 409]
|
378
481
|
codes.each do |code|
|
@@ -384,7 +487,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
384
487
|
|
385
488
|
context 'with default :retry option' do
|
386
489
|
it 'marks endpoints as bad if they encounter retryable errors' do
|
387
|
-
rb =
|
490
|
+
rb = described_class.new([1,2,3], :policy => RightSupport::Net::LB::HealthCheck, :health_check => Proc.new {|endpoint| false})
|
388
491
|
expect = rb.get_stats
|
389
492
|
codes = [401, 402, 403, 404, 405, 406, 407, 408, 409]
|
390
493
|
codes.each do |code|
|
@@ -397,7 +500,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
397
500
|
end
|
398
501
|
|
399
502
|
it 'does not mark endpoints as bad if they raise fatal errors' do
|
400
|
-
rb =
|
503
|
+
rb = described_class.new([1,2,3], :policy => RightSupport::Net::LB::HealthCheck, :health_check => Proc.new {|endpoint| false})
|
401
504
|
codes = [401, 402, 403, 404, 405, 406, 407, 409]
|
402
505
|
codes.each do |code|
|
403
506
|
lambda do
|
@@ -420,7 +523,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
420
523
|
@callback.should_receive(:respond_to?).with(:call).and_return(true)
|
421
524
|
@callback.should_receive(:respond_to?).with(:arity).and_return(true)
|
422
525
|
@callback.should_receive(:arity).and_return(3)
|
423
|
-
@rb =
|
526
|
+
@rb = described_class.new(@list, :fatal=>BigDeal, :on_exception=>@callback)
|
424
527
|
end
|
425
528
|
|
426
529
|
it 'calls me back with fatal exceptions' do
|
@@ -442,12 +545,12 @@ describe RightSupport::Net::RequestBalancer do
|
|
442
545
|
context 'given a class-level logger' do
|
443
546
|
before(:all) do
|
444
547
|
@logger = Logger.new(StringIO.new)
|
445
|
-
|
548
|
+
described_class.logger = @logger
|
446
549
|
RightSupport::Net::LB::HealthCheck.logger = @logger
|
447
550
|
end
|
448
551
|
|
449
552
|
after(:all) do
|
450
|
-
|
553
|
+
described_class.logger = nil
|
451
554
|
end
|
452
555
|
|
453
556
|
context 'when a retryable exception is raised' do
|
@@ -455,7 +558,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
455
558
|
flexmock(@logger).should_receive(:error).times(4)
|
456
559
|
|
457
560
|
lambda {
|
458
|
-
balancer =
|
561
|
+
balancer = described_class.new([1,2,3])
|
459
562
|
balancer.request do |ep|
|
460
563
|
raise NoBigDeal, "Too many cows on the moon"
|
461
564
|
end
|
@@ -471,7 +574,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
471
574
|
flexmock(@logger).should_receive(:info).times(8)
|
472
575
|
|
473
576
|
lambda {
|
474
|
-
balancer =
|
577
|
+
balancer = described_class.new([1,2,3,4], :policy => RightSupport::Net::LB::HealthCheck, :health_check => health_check)
|
475
578
|
balancer.request do |ep|
|
476
579
|
raise "Bad Endpoint"
|
477
580
|
end
|
@@ -498,7 +601,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
498
601
|
|
499
602
|
it 'resolves ip addresses for specified list of endpoints' do
|
500
603
|
@dns.should_receive(:resolve_with_hostnames).with(@endpoints).and_return(@resolved_set_1)
|
501
|
-
@rb =
|
604
|
+
@rb = described_class.new(@endpoints, :resolve => 15)
|
502
605
|
|
503
606
|
@rb.request { true }
|
504
607
|
@policy = @rb.instance_variable_get("@policy")
|
@@ -507,7 +610,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
507
610
|
|
508
611
|
it 're-resolves list of ip addresses if TTL is expired' do
|
509
612
|
@dns.should_receive(:resolve_with_hostnames).with(@endpoints).twice.and_return(@resolved_set_1, @resolved_set_2)
|
510
|
-
@rb =
|
613
|
+
@rb = described_class.new(@endpoints, :resolve => 15)
|
511
614
|
|
512
615
|
@rb.request { true }
|
513
616
|
@policy = @rb.instance_variable_get("@policy")
|
@@ -524,7 +627,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
524
627
|
before(:each) do
|
525
628
|
@endpoints = [1,2,3,4,5,6]
|
526
629
|
@exceptions = [BigDeal, NoBigDeal, OtherTestException]
|
527
|
-
@rb =
|
630
|
+
@rb = described_class.new(@endpoints)
|
528
631
|
@tries = 0
|
529
632
|
begin
|
530
633
|
@rb.request do |ep|
|
@@ -564,7 +667,7 @@ describe RightSupport::Net::RequestBalancer do
|
|
564
667
|
expected_hash = {}
|
565
668
|
list = [1,2,3,4]
|
566
669
|
list.each { |k| expected_hash[k] = 'n/a' }
|
567
|
-
rb =
|
670
|
+
rb = described_class.new(list)
|
568
671
|
|
569
672
|
rb.get_stats.should_not be_nil
|
570
673
|
rb.get_stats.should == expected_hash
|
@@ -575,9 +678,10 @@ describe RightSupport::Net::RequestBalancer do
|
|
575
678
|
it 'returns stats in an endpoint-keyed hash' do
|
576
679
|
expected_hash = {}
|
577
680
|
list = [1,2,3,4]
|
578
|
-
rb =
|
579
|
-
|
580
|
-
|
681
|
+
rb = described_class.new(
|
682
|
+
list,
|
683
|
+
:policy => RightSupport::Net::LB::HealthCheck,
|
684
|
+
:health_check => Proc.new {|endpoint| "HealthCheck passed for #{endpoint}!"})
|
581
685
|
rb.get_stats.should_not be_nil
|
582
686
|
rb.get_stats.should_not == expected_hash
|
583
687
|
end
|