elasticsearch-transport 7.1.0 → 7.8.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 +4 -4
- data/Gemfile +12 -8
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +160 -72
- data/Rakefile +1 -1
- data/elasticsearch-transport.gemspec +42 -60
- data/lib/elasticsearch/transport/client.rb +70 -19
- data/lib/elasticsearch/transport/redacted.rb +1 -1
- data/lib/elasticsearch/transport/transport/base.rb +86 -12
- data/lib/elasticsearch/transport/transport/connections/collection.rb +1 -1
- data/lib/elasticsearch/transport/transport/connections/connection.rb +1 -1
- data/lib/elasticsearch/transport/transport/connections/selector.rb +18 -6
- data/lib/elasticsearch/transport/transport/errors.rb +1 -1
- data/lib/elasticsearch/transport/transport/http/curb.rb +26 -9
- data/lib/elasticsearch/transport/transport/http/faraday.rb +18 -4
- data/lib/elasticsearch/transport/transport/http/manticore.rb +25 -10
- data/lib/elasticsearch/transport/transport/loggable.rb +1 -1
- data/lib/elasticsearch/transport/transport/response.rb +1 -2
- data/lib/elasticsearch/transport/transport/serializer/multi_json.rb +1 -1
- data/lib/elasticsearch/transport/transport/sniffer.rb +3 -2
- data/lib/elasticsearch/transport/version.rb +2 -2
- data/lib/elasticsearch/transport.rb +1 -1
- data/lib/elasticsearch-transport.rb +1 -1
- data/spec/elasticsearch/connections/collection_spec.rb +254 -0
- data/spec/elasticsearch/connections/selector_spec.rb +174 -0
- data/spec/elasticsearch/transport/base_spec.rb +177 -9
- data/spec/elasticsearch/transport/client_spec.rb +525 -29
- data/spec/elasticsearch/transport/sniffer_spec.rb +1 -1
- data/spec/spec_helper.rb +25 -1
- data/test/integration/transport_test.rb +1 -1
- data/test/profile/client_benchmark_test.rb +1 -1
- data/test/test_helper.rb +1 -1
- data/test/unit/connection_test.rb +1 -1
- data/test/unit/response_test.rb +2 -2
- data/test/unit/serializer_test.rb +1 -1
- data/test/unit/transport_base_test.rb +1 -1
- data/test/unit/transport_curb_test.rb +2 -2
- data/test/unit/transport_faraday_test.rb +1 -1
- data/test/unit/transport_manticore_test.rb +28 -12
- metadata +85 -61
- data/test/unit/connection_collection_test.rb +0 -147
- data/test/unit/connection_selector_test.rb +0 -81
| @@ -0,0 +1,254 @@ | |
| 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 | 
            +
                    20.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 | 
            +
                   expect(10.times.collect do
         | 
| 242 | 
            +
                      threads = []
         | 
| 243 | 
            +
                      20.times do
         | 
| 244 | 
            +
                        threads << Thread.new do
         | 
| 245 | 
            +
                          collection.get_connection
         | 
| 246 | 
            +
                        end
         | 
| 247 | 
            +
                      end
         | 
| 248 | 
            +
                      threads.map { |t| t.join }
         | 
| 249 | 
            +
                      collection.get_connection.host[:host]
         | 
| 250 | 
            +
                    end).to eq((0..9).to_a)
         | 
| 251 | 
            +
                  end
         | 
| 252 | 
            +
                end
         | 
| 253 | 
            +
              end
         | 
| 254 | 
            +
            end
         | 
| @@ -0,0 +1,174 @@ | |
| 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::Selector do
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              before do
         | 
| 23 | 
            +
                class BackupStrategySelector
         | 
| 24 | 
            +
                  include Elasticsearch::Transport::Transport::Connections::Selector::Base
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def select(options={})
         | 
| 27 | 
            +
                    connections.reject do |c|
         | 
| 28 | 
            +
                      c.host[:attributes] && c.host[:attributes][:backup]
         | 
| 29 | 
            +
                    end.sample
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              after do
         | 
| 35 | 
            +
                Object.send(:remove_const, :BackupStrategySelector)
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              let(:backup_strategy_selector) do
         | 
| 39 | 
            +
                BackupStrategySelector.new
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              describe 'the Random selector' do
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                let(:connections) do
         | 
| 45 | 
            +
                  [1, 2]
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                let(:selector) do
         | 
| 49 | 
            +
                  described_class::Random.new(connections: connections)
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                it 'is initialized with connections' do
         | 
| 53 | 
            +
                  expect(selector.connections).to eq(connections)
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                describe '#select' do
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                  let(:connections) do
         | 
| 59 | 
            +
                    (0..19).to_a
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                  it 'returns a connection' do
         | 
| 63 | 
            +
                    expect(selector.select).to be_a(Integer)
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  context 'when multiple threads are used' do
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    it 'allows threads to select connections in parallel' do
         | 
| 69 | 
            +
                      expect(10.times.collect do
         | 
| 70 | 
            +
                        threads = []
         | 
| 71 | 
            +
                        20.times do
         | 
| 72 | 
            +
                          threads << Thread.new do
         | 
| 73 | 
            +
                            selector.select
         | 
| 74 | 
            +
                          end
         | 
| 75 | 
            +
                        end
         | 
| 76 | 
            +
                        threads.map { |t| t.join }
         | 
| 77 | 
            +
                        selector.select
         | 
| 78 | 
            +
                      end).to all(be_a(Integer))
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
              end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              describe 'the RoundRobin selector' do
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                let(:connections) do
         | 
| 87 | 
            +
                  ['A', 'B', 'C']
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                let(:selector) do
         | 
| 91 | 
            +
                  described_class::RoundRobin.new(connections: connections)
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                it 'is initialized with connections' do
         | 
| 95 | 
            +
                  expect(selector.connections).to eq(connections)
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                describe '#select' do
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  it 'rotates over the connections' do
         | 
| 101 | 
            +
                    expect(selector.select).to eq('A')
         | 
| 102 | 
            +
                    expect(selector.select).to eq('B')
         | 
| 103 | 
            +
                    expect(selector.select).to eq('C')
         | 
| 104 | 
            +
                    expect(selector.select).to eq('A')
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  context 'when multiple threads are used' do
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                    let(:connections) do
         | 
| 110 | 
            +
                      (0..19).to_a
         | 
| 111 | 
            +
                    end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                    it 'returns a connection' do
         | 
| 114 | 
            +
                      expect(selector.select).to be_a(Integer)
         | 
| 115 | 
            +
                    end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                    it 'allows threads to select connections in parallel' do
         | 
| 118 | 
            +
                      expect(10.times.collect do
         | 
| 119 | 
            +
                        threads = []
         | 
| 120 | 
            +
                        20.times do
         | 
| 121 | 
            +
                          threads << Thread.new do
         | 
| 122 | 
            +
                            selector.select
         | 
| 123 | 
            +
                          end
         | 
| 124 | 
            +
                        end
         | 
| 125 | 
            +
                        threads.map { |t| t.join }
         | 
| 126 | 
            +
                        selector.select
         | 
| 127 | 
            +
                      end).to eq((0..9).to_a)
         | 
| 128 | 
            +
                    end
         | 
| 129 | 
            +
                  end
         | 
| 130 | 
            +
                end
         | 
| 131 | 
            +
              end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
              describe 'a custom selector' do
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                let(:connections) do
         | 
| 136 | 
            +
                  [ double(host: { hostname: 'host1' }),
         | 
| 137 | 
            +
                    double(host: { hostname: 'host2', attributes: { backup: true } }) ]
         | 
| 138 | 
            +
                end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                let(:selector) do
         | 
| 141 | 
            +
                  BackupStrategySelector.new(connections: connections)
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                it 'is initialized with connections' do
         | 
| 145 | 
            +
                  expect(selector.connections).to eq(connections)
         | 
| 146 | 
            +
                end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                describe '#select' do
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                  it 'applies the custom strategy' do
         | 
| 151 | 
            +
                    10.times { expect(selector.select.host[:hostname]).to eq('host1') }
         | 
| 152 | 
            +
                  end
         | 
| 153 | 
            +
                end
         | 
| 154 | 
            +
              end
         | 
| 155 | 
            +
             | 
| 156 | 
            +
              context 'when the Base module is included in a class' do
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                before do
         | 
| 159 | 
            +
                  class ExampleSelector
         | 
| 160 | 
            +
                    include Elasticsearch::Transport::Transport::Connections::Selector::Base
         | 
| 161 | 
            +
                  end
         | 
| 162 | 
            +
                end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                after do
         | 
| 165 | 
            +
                  Object.send(:remove_const, :ExampleSelector)
         | 
| 166 | 
            +
                end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                it 'requires the #select method to be redefined' do
         | 
| 169 | 
            +
                  expect {
         | 
| 170 | 
            +
                    ExampleSelector.new.select
         | 
| 171 | 
            +
                  }.to raise_exception(NoMethodError)
         | 
| 172 | 
            +
                end
         | 
| 173 | 
            +
              end
         | 
| 174 | 
            +
            end
         | 
| @@ -6,7 +6,7 @@ | |
| 6 6 | 
             
            # not use this file except in compliance with the License.
         | 
| 7 7 | 
             
            # You may obtain a copy of the License at
         | 
| 8 8 | 
             
            #
         | 
| 9 | 
            -
            # | 
| 9 | 
            +
            #   http://www.apache.org/licenses/LICENSE-2.0
         | 
| 10 10 | 
             
            #
         | 
| 11 11 | 
             
            # Unless required by applicable law or agreed to in writing,
         | 
| 12 12 | 
             
            # software distributed under the License is distributed on an
         | 
| @@ -18,11 +18,8 @@ | |
| 18 18 | 
             
            require 'spec_helper'
         | 
| 19 19 |  | 
| 20 20 | 
             
            describe Elasticsearch::Transport::Transport::Base do
         | 
| 21 | 
            -
             | 
| 22 21 | 
             
              context 'when a host is printed in a logged message' do
         | 
| 23 | 
            -
             | 
| 24 22 | 
             
                shared_examples_for 'a redacted string' do
         | 
| 25 | 
            -
             | 
| 26 23 | 
             
                  let(:client) do
         | 
| 27 24 | 
             
                    Elasticsearch::Transport::Client.new(arguments)
         | 
| 28 25 | 
             
                  end
         | 
| @@ -33,6 +30,7 @@ describe Elasticsearch::Transport::Transport::Base do | |
| 33 30 |  | 
| 34 31 | 
             
                  it 'does not include the password in the logged string' do
         | 
| 35 32 | 
             
                    expect(logger).not_to receive(:error).with(/secret_password/)
         | 
| 33 | 
            +
             | 
| 36 34 | 
             
                    expect {
         | 
| 37 35 | 
             
                      client.cluster.stats
         | 
| 38 36 | 
             
                    }.to raise_exception(Faraday::ConnectionFailed)
         | 
| @@ -47,7 +45,6 @@ describe Elasticsearch::Transport::Transport::Base do | |
| 47 45 | 
             
                end
         | 
| 48 46 |  | 
| 49 47 | 
             
                context 'when the user and password are provided as separate arguments' do
         | 
| 50 | 
            -
             | 
| 51 48 | 
             
                  let(:arguments) do
         | 
| 52 49 | 
             
                    { hosts: 'fake',
         | 
| 53 50 | 
             
                      logger: logger,
         | 
| @@ -59,9 +56,8 @@ describe Elasticsearch::Transport::Transport::Base do | |
| 59 56 | 
             
                end
         | 
| 60 57 |  | 
| 61 58 | 
             
                context 'when the user and password are provided in the string URI' do
         | 
| 62 | 
            -
             | 
| 63 59 | 
             
                  let(:arguments) do
         | 
| 64 | 
            -
                    { hosts: ' | 
| 60 | 
            +
                    { hosts: 'https://test:secret_password@fake_local_elasticsearch',
         | 
| 65 61 | 
             
                      logger: logger }
         | 
| 66 62 | 
             
                  end
         | 
| 67 63 |  | 
| @@ -69,13 +65,185 @@ describe Elasticsearch::Transport::Transport::Base do | |
| 69 65 | 
             
                end
         | 
| 70 66 |  | 
| 71 67 | 
             
                context 'when the user and password are provided in the URI object' do
         | 
| 72 | 
            -
             | 
| 73 68 | 
             
                  let(:arguments) do
         | 
| 74 | 
            -
                    { hosts: URI.parse(' | 
| 69 | 
            +
                    { hosts: URI.parse('https://test:secret_password@fake_local_elasticsearch'),
         | 
| 75 70 | 
             
                      logger: logger }
         | 
| 76 71 | 
             
                  end
         | 
| 77 72 |  | 
| 78 73 | 
             
                  it_behaves_like 'a redacted string'
         | 
| 79 74 | 
             
                end
         | 
| 80 75 | 
             
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              context 'when reload_on_failure is true and and hosts are unreachable' do
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                let(:client) do
         | 
| 80 | 
            +
                  Elasticsearch::Transport::Client.new(arguments)
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                let(:arguments) do
         | 
| 84 | 
            +
                  {
         | 
| 85 | 
            +
                      hosts: ['http://unavailable:9200', 'http://unavailable:9201'],
         | 
| 86 | 
            +
                      reload_on_failure: true,
         | 
| 87 | 
            +
                      sniffer_timeout: 5
         | 
| 88 | 
            +
                  }
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                it 'raises an exception' do
         | 
| 92 | 
            +
                  expect {
         | 
| 93 | 
            +
                    client.info
         | 
| 94 | 
            +
                  }.to raise_exception(Faraday::ConnectionFailed)
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
              end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
              context 'when the client has `retry_on_failure` set to an integer' do
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                let(:client) do
         | 
| 101 | 
            +
                  Elasticsearch::Transport::Client.new(arguments)
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                let(:arguments) do
         | 
| 105 | 
            +
                  {
         | 
| 106 | 
            +
                      hosts: ['http://unavailable:9200', 'http://unavailable:9201'],
         | 
| 107 | 
            +
                      retry_on_failure: 2
         | 
| 108 | 
            +
                  }
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                context 'when `perform_request` is called without a `retry_on_failure` option value' do
         | 
| 112 | 
            +
                  before do
         | 
| 113 | 
            +
                    expect(client.transport).to receive(:get_connection).exactly(3).times.and_call_original
         | 
| 114 | 
            +
                  end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                  it 'uses the client `retry_on_failure` value' do
         | 
| 117 | 
            +
                    expect {
         | 
| 118 | 
            +
                      client.transport.perform_request('GET', '/info')
         | 
| 119 | 
            +
                    }.to raise_exception(Faraday::ConnectionFailed)
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                context 'when `perform_request` is called with a `retry_on_failure` option value' do
         | 
| 124 | 
            +
                  before do
         | 
| 125 | 
            +
                    expect(client.transport).to receive(:get_connection).exactly(6).times.and_call_original
         | 
| 126 | 
            +
                  end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                  it 'uses the option `retry_on_failure` value' do
         | 
| 129 | 
            +
                    expect {
         | 
| 130 | 
            +
                      client.transport.perform_request('GET', '/info', {}, nil, nil, retry_on_failure: 5)
         | 
| 131 | 
            +
                    }.to raise_exception(Faraday::ConnectionFailed)
         | 
| 132 | 
            +
                  end
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
              end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
              context 'when the client has `retry_on_failure` set to true' do
         | 
| 137 | 
            +
                let(:client) do
         | 
| 138 | 
            +
                  Elasticsearch::Transport::Client.new(arguments)
         | 
| 139 | 
            +
                end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                let(:arguments) do
         | 
| 142 | 
            +
                  {
         | 
| 143 | 
            +
                      hosts: ['http://unavailable:9200', 'http://unavailable:9201'],
         | 
| 144 | 
            +
                      retry_on_failure: true
         | 
| 145 | 
            +
                  }
         | 
| 146 | 
            +
                end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                context 'when `perform_request` is called without a `retry_on_failure` option value' do
         | 
| 149 | 
            +
                  before do
         | 
| 150 | 
            +
                    expect(client.transport).to receive(:get_connection).exactly(4).times.and_call_original
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                  it 'uses the default `MAX_RETRIES` value' do
         | 
| 154 | 
            +
                    expect {
         | 
| 155 | 
            +
                      client.transport.perform_request('GET', '/info')
         | 
| 156 | 
            +
                    }.to raise_exception(Faraday::ConnectionFailed)
         | 
| 157 | 
            +
                  end
         | 
| 158 | 
            +
                end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                context 'when `perform_request` is called with a `retry_on_failure` option value' do
         | 
| 161 | 
            +
                  before do
         | 
| 162 | 
            +
                    expect(client.transport).to receive(:get_connection).exactly(6).times.and_call_original
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                  it 'uses the option `retry_on_failure` value' do
         | 
| 166 | 
            +
                    expect {
         | 
| 167 | 
            +
                      client.transport.perform_request('GET', '/info', {}, nil, nil, retry_on_failure: 5)
         | 
| 168 | 
            +
                    }.to raise_exception(Faraday::ConnectionFailed)
         | 
| 169 | 
            +
                  end
         | 
| 170 | 
            +
                end
         | 
| 171 | 
            +
              end
         | 
| 172 | 
            +
             | 
| 173 | 
            +
              context 'when the client has `retry_on_failure` set to false' do
         | 
| 174 | 
            +
                let(:client) do
         | 
| 175 | 
            +
                  Elasticsearch::Transport::Client.new(arguments)
         | 
| 176 | 
            +
                end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                let(:arguments) do
         | 
| 179 | 
            +
                  {
         | 
| 180 | 
            +
                      hosts: ['http://unavailable:9200', 'http://unavailable:9201'],
         | 
| 181 | 
            +
                      retry_on_failure: false
         | 
| 182 | 
            +
                  }
         | 
| 183 | 
            +
                end
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                context 'when `perform_request` is called without a `retry_on_failure` option value' do
         | 
| 186 | 
            +
                  before do
         | 
| 187 | 
            +
                    expect(client.transport).to receive(:get_connection).once.and_call_original
         | 
| 188 | 
            +
                  end
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                  it 'does not retry' do
         | 
| 191 | 
            +
                    expect {
         | 
| 192 | 
            +
                      client.transport.perform_request('GET', '/info')
         | 
| 193 | 
            +
                    }.to raise_exception(Faraday::ConnectionFailed)
         | 
| 194 | 
            +
                  end
         | 
| 195 | 
            +
                end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
                context 'when `perform_request` is called with a `retry_on_failure` option value' do
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                  before do
         | 
| 200 | 
            +
                    expect(client.transport).to receive(:get_connection).exactly(6).times.and_call_original
         | 
| 201 | 
            +
                  end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                  it 'uses the option `retry_on_failure` value' do
         | 
| 204 | 
            +
                    expect {
         | 
| 205 | 
            +
                      client.transport.perform_request('GET', '/info', {}, nil, nil, retry_on_failure: 5)
         | 
| 206 | 
            +
                    }.to raise_exception(Faraday::ConnectionFailed)
         | 
| 207 | 
            +
                  end
         | 
| 208 | 
            +
                end
         | 
| 209 | 
            +
              end
         | 
| 210 | 
            +
             | 
| 211 | 
            +
              context 'when the client has no `retry_on_failure` set' do
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                let(:client) do
         | 
| 214 | 
            +
                  Elasticsearch::Transport::Client.new(arguments)
         | 
| 215 | 
            +
                end
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                let(:arguments) do
         | 
| 218 | 
            +
                  {
         | 
| 219 | 
            +
                      hosts: ['http://unavailable:9200', 'http://unavailable:9201'],
         | 
| 220 | 
            +
                  }
         | 
| 221 | 
            +
                end
         | 
| 222 | 
            +
             | 
| 223 | 
            +
                context 'when `perform_request` is called without a `retry_on_failure` option value' do
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                  before do
         | 
| 226 | 
            +
                    expect(client.transport).to receive(:get_connection).exactly(1).times.and_call_original
         | 
| 227 | 
            +
                  end
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                  it 'does not retry' do
         | 
| 230 | 
            +
                    expect {
         | 
| 231 | 
            +
                      client.transport.perform_request('GET', '/info')
         | 
| 232 | 
            +
                    }.to raise_exception(Faraday::ConnectionFailed)
         | 
| 233 | 
            +
                  end
         | 
| 234 | 
            +
                end
         | 
| 235 | 
            +
             | 
| 236 | 
            +
                context 'when `perform_request` is called with a `retry_on_failure` option value' do
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                  before do
         | 
| 239 | 
            +
                    expect(client.transport).to receive(:get_connection).exactly(6).times.and_call_original
         | 
| 240 | 
            +
                  end
         | 
| 241 | 
            +
             | 
| 242 | 
            +
                  it 'uses the option `retry_on_failure` value' do
         | 
| 243 | 
            +
                    expect {
         | 
| 244 | 
            +
                      client.transport.perform_request('GET', '/info', {}, nil, nil, retry_on_failure: 5)
         | 
| 245 | 
            +
                    }.to raise_exception(Faraday::ConnectionFailed)
         | 
| 246 | 
            +
                  end
         | 
| 247 | 
            +
                end
         | 
| 248 | 
            +
              end
         | 
| 81 249 | 
             
            end
         |