diff --git a/Gemfile b/Gemfile index aaa095dfcd71cca5f0923f768237b0fbf9b161c5..9d4eef8ae43ed445d5bc6d2ec1ea71da5b28cf4e 100644 --- a/Gemfile +++ b/Gemfile @@ -149,6 +149,7 @@ gem 'aws-sdk-core', '~> 3' gem 'aws-sdk-cloudformation', '~> 1' gem 'aws-sdk-s3', '~> 1' gem 'faraday_middleware-aws-sigv4', '~>0.3.0' +gem 'typhoeus', '~> 1.4.0' # Used with Elasticsearch to support http keep-alive connections # Markdown and HTML processing gem 'html-pipeline', '~> 2.13.2' diff --git a/Gemfile.lock b/Gemfile.lock index 45c916bbf767f3d1ff0e43349057d0956e34526d..8b811cafe68cfe80c9ed52bef01b2a18ea710b2b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -333,6 +333,8 @@ GEM escape_utils (1.2.1) et-orbi (1.2.1) tzinfo + ethon (0.15.0) + ffi (>= 1.15.0) eventmachine (1.2.7) excon (0.71.1) execjs (2.8.1) @@ -1311,6 +1313,8 @@ GEM tty-screen (~> 0.8) wisper (~> 2.0) tty-screen (0.8.1) + typhoeus (1.4.0) + ethon (>= 0.9.0) tzinfo (2.0.4) concurrent-ruby (~> 1.0) u2f (0.2.1) @@ -1655,6 +1659,7 @@ DEPENDENCIES timecop (~> 0.9.1) toml-rb (~> 2.0) truncato (~> 0.7.11) + typhoeus (~> 1.4.0) u2f (~> 0.2.1) undercover (~> 0.4.4) unf (~> 0.1.4) diff --git a/config/feature_flags/development/use_typhoeus_elasticsearch_adapter.yml b/config/feature_flags/development/use_typhoeus_elasticsearch_adapter.yml new file mode 100644 index 0000000000000000000000000000000000000000..ac762395cd2fc91c232038dd0cba82760019b48d --- /dev/null +++ b/config/feature_flags/development/use_typhoeus_elasticsearch_adapter.yml @@ -0,0 +1,8 @@ +--- +name: use_typhoeus_elasticsearch_adapter +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76879 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348607 +milestone: '14.7' +type: development +group: group::global search +default_enabled: false diff --git a/ee/lib/gem_extensions/elasticsearch/model/client.rb b/ee/lib/gem_extensions/elasticsearch/model/client.rb index cdf0fa4d63a37cd9e62e74ce071d7abe94db1c13..d9854e24e4bf7cb415db27dcad77aff448a2d341 100644 --- a/ee/lib/gem_extensions/elasticsearch/model/client.rb +++ b/ee/lib/gem_extensions/elasticsearch/model/client.rb @@ -15,16 +15,19 @@ module Client cattr_accessor :cached_client cattr_accessor :cached_config + cattr_accessor :cached_adapter def client(_client = nil) store = ::GemExtensions::Elasticsearch::Model::Client store::CLIENT_MUTEX.synchronize do - config = Gitlab::CurrentSettings.elasticsearch_config + config = ::Gitlab::CurrentSettings.elasticsearch_config + adapter = ::Gitlab::Elastic::Client.adapter - if store.cached_client.nil? || config != store.cached_config + if store.cached_client.nil? || config != store.cached_config || adapter != store.cached_adapter store.cached_client = ::Gitlab::Elastic::Client.build(config) store.cached_config = config + store.cached_adapter = adapter end end diff --git a/ee/lib/gitlab/elastic/client.rb b/ee/lib/gitlab/elastic/client.rb index 00175bcd219e25136486f87d1a904adb8c5702bb..d2292882095e9218da0f4f4d358039693304cb74 100644 --- a/ee/lib/gitlab/elastic/client.rb +++ b/ee/lib/gitlab/elastic/client.rb @@ -14,6 +14,7 @@ module Client # and configures itself based on those parameters def self.build(config) base_config = { + adapter: self.adapter, urls: config[:url], transport_options: { request: { @@ -37,6 +38,10 @@ def self.build(config) end end + def self.adapter + ::Feature.enabled?(:use_typhoeus_elasticsearch_adapter) ? :typhoeus : :net_http + end + def self.resolve_aws_credentials(config) # Resolve credentials in order # 1. Static config diff --git a/ee/spec/lib/gitlab/elastic/client_spec.rb b/ee/spec/lib/gitlab/elastic/client_spec.rb index f5a0d6006591d2b43af8826b2aa5b675dab517e8..1472efc8625d151836112c32fcf48f751e163b2c 100644 --- a/ee/spec/lib/gitlab/elastic/client_spec.rb +++ b/ee/spec/lib/gitlab/elastic/client_spec.rb @@ -23,6 +23,37 @@ expect(options).to include(open_timeout: described_class::OPEN_TIMEOUT, timeout: nil) end + context 'with typhoeus adapter for keep-alive connections' do + it 'sets typhoeus as the adapter' do + options = client.transport.options + + expect(options).to include(adapter: :typhoeus) + end + + context 'when use_typhoeus_elasticsearch_adapter FeatureFlag is disabled' do + before do + stub_feature_flags(use_typhoeus_elasticsearch_adapter: false) + end + + it 'uses the net/http adapter' do + options = client.transport.options + expect(options).to include(adapter: :net_http) + end + end + + context 'cached client when FeatureFlag changes' do + it 'successfully changes adapter from net/http to typhoeus' do + stub_feature_flags(use_typhoeus_elasticsearch_adapter: false) + adapter = Issue.__elasticsearch__.client.transport.connections.first.connection.builder.adapter + expect(adapter).to eq(::Faraday::Adapter::NetHttp) + + stub_feature_flags(use_typhoeus_elasticsearch_adapter: true) + adapter = Issue.__elasticsearch__.client.transport.connections.first.connection.builder.adapter + expect(adapter).to eq(::Faraday::Adapter::Typhoeus) + end + end + end + context 'with client_request_timeout in config' do let(:params) { { url: 'http://dummy-elastic:9200', client_request_timeout: 30 } }