Skip to content

Commit 0071be9

Browse files
committed
[CLIENT] Test selecting connections using multiple threads
1 parent e11c394 commit 0071be9

File tree

4 files changed

+407
-228
lines changed

4 files changed

+407
-228
lines changed
Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
# Licensed to Elasticsearch B.V. under one or more contributor
2+
# license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
require 'spec_helper'
19+
20+
describe Elasticsearch::Transport::Transport::Connections::Collection do
21+
22+
describe '#initialize' do
23+
24+
let(:collection) do
25+
described_class.new
26+
end
27+
28+
it 'has an empty list of connections as a default' do
29+
expect(collection.connections).to be_empty
30+
end
31+
32+
it 'has a default selector class' do
33+
expect(collection.selector).not_to be_nil
34+
end
35+
36+
context 'when a selector class is specified' do
37+
38+
let(:collection) do
39+
described_class.new(selector_class: Elasticsearch::Transport::Transport::Connections::Selector::Random)
40+
end
41+
42+
it 'sets the selector' do
43+
expect(collection.selector).to be_a(Elasticsearch::Transport::Transport::Connections::Selector::Random)
44+
end
45+
end
46+
end
47+
48+
describe '#get_connection' do
49+
50+
let(:collection) do
51+
described_class.new(selector_class: Elasticsearch::Transport::Transport::Connections::Selector::Random)
52+
end
53+
54+
before do
55+
expect(collection.selector).to receive(:select).and_return('OK')
56+
end
57+
58+
it 'uses the selector to select a connection' do
59+
expect(collection.get_connection).to eq('OK')
60+
end
61+
end
62+
63+
describe '#hosts' do
64+
65+
let(:collection) do
66+
described_class.new(connections: [ double('connection', host: 'A'),
67+
double('connection', host: 'B') ])
68+
end
69+
70+
it 'returns a list of hosts' do
71+
expect(collection.hosts).to eq([ 'A', 'B'])
72+
end
73+
end
74+
75+
describe 'enumerable' do
76+
77+
let(:collection) do
78+
described_class.new(connections: [ double('connection', host: 'A', dead?: false),
79+
double('connection', host: 'B', dead?: false) ])
80+
end
81+
82+
describe '#map' do
83+
84+
it 'responds to the method' do
85+
expect(collection.map { |c| c.host.downcase }).to eq(['a', 'b'])
86+
end
87+
end
88+
89+
describe '#[]' do
90+
91+
it 'responds to the method' do
92+
expect(collection[0].host).to eq('A')
93+
expect(collection[1].host).to eq('B')
94+
end
95+
end
96+
97+
describe '#size' do
98+
99+
it 'responds to the method' do
100+
expect(collection.size).to eq(2)
101+
end
102+
end
103+
104+
context 'when a connection is marked as dead' do
105+
106+
let(:collection) do
107+
described_class.new(connections: [ double('connection', host: 'A', dead?: true),
108+
double('connection', host: 'B', dead?: false) ])
109+
end
110+
111+
it 'does not enumerate the dead connections' do
112+
expect(collection.size).to eq(1)
113+
expect(collection.collect { |c| c.host }).to eq(['B'])
114+
end
115+
116+
context '#alive' do
117+
118+
it 'enumerates the alive connections' do
119+
expect(collection.alive.collect { |c| c.host }).to eq(['B'])
120+
end
121+
end
122+
123+
context '#dead' do
124+
125+
it 'enumerates the alive connections' do
126+
expect(collection.dead.collect { |c| c.host }).to eq(['A'])
127+
end
128+
end
129+
end
130+
end
131+
132+
describe '#add' do
133+
134+
let(:collection) do
135+
described_class.new(connections: [ double('connection', host: 'A', dead?: false),
136+
double('connection', host: 'B', dead?: false) ])
137+
end
138+
139+
context 'when an array is provided' do
140+
141+
before do
142+
collection.add([double('connection', host: 'C', dead?: false),
143+
double('connection', host: 'D', dead?: false)])
144+
end
145+
146+
it 'adds the connections' do
147+
expect(collection.size).to eq(4)
148+
end
149+
end
150+
151+
context 'when an element is provided' do
152+
153+
before do
154+
collection.add(double('connection', host: 'C', dead?: false))
155+
end
156+
157+
it 'adds the connection' do
158+
expect(collection.size).to eq(3)
159+
end
160+
end
161+
end
162+
163+
describe '#remove' do
164+
165+
let(:connections) do
166+
[ double('connection', host: 'A', dead?: false),
167+
double('connection', host: 'B', dead?: false) ]
168+
end
169+
170+
let(:collection) do
171+
described_class.new(connections: connections)
172+
end
173+
174+
context 'when an array is provided' do
175+
176+
before do
177+
collection.remove(connections)
178+
end
179+
180+
it 'removes the connections' do
181+
expect(collection.size).to eq(0)
182+
end
183+
end
184+
185+
context 'when an element is provided' do
186+
187+
let(:connections) do
188+
[ double('connection', host: 'A', dead?: false),
189+
double('connection', host: 'B', dead?: false) ]
190+
end
191+
192+
before do
193+
collection.remove(connections.first)
194+
end
195+
196+
it 'removes the connection' do
197+
expect(collection.size).to eq(1)
198+
end
199+
end
200+
end
201+
202+
describe '#get_connection' do
203+
204+
context 'when all connections are dead' do
205+
206+
let(:connection_a) do
207+
Elasticsearch::Transport::Transport::Connections::Connection.new(host: { host: 'A' })
208+
end
209+
210+
let(:connection_b) do
211+
Elasticsearch::Transport::Transport::Connections::Connection.new(host: { host: 'B' })
212+
end
213+
214+
let(:collection) do
215+
described_class.new(connections: [connection_a, connection_b])
216+
end
217+
218+
before do
219+
connection_a.dead!.dead!
220+
connection_b.dead!
221+
end
222+
223+
it 'returns the connection with the least failures' do
224+
expect(collection.get_connection.host[:host]).to eq('B')
225+
end
226+
end
227+
228+
context 'when multiple threads are used' do
229+
230+
let(:connections) do
231+
100.times.collect do |i|
232+
Elasticsearch::Transport::Transport::Connections::Connection.new(host: { host: i })
233+
end
234+
end
235+
236+
let(:collection) do
237+
described_class.new(connections: connections)
238+
end
239+
240+
it 'allows threads to select connections in parallel' do
241+
threads = []
242+
threads << Thread.new do
243+
2000.times do |i|
244+
collection.get_connection
245+
end
246+
end
247+
threads.collect {|t| t.join}
248+
end
249+
end
250+
end
251+
end

0 commit comments

Comments
 (0)