diff --git a/ee/config/feature_flags/gitlab_com_derisk/search_client_adapter_options.yml b/ee/config/feature_flags/gitlab_com_derisk/search_client_adapter_options.yml new file mode 100644 index 0000000000000000000000000000000000000000..795f35fdd6c95da2a96fbabcce056a6f86665bf2 --- /dev/null +++ b/ee/config/feature_flags/gitlab_com_derisk/search_client_adapter_options.yml @@ -0,0 +1,10 @@ +--- +name: search_client_adapter_options +description: +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/550805 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/203919 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/568114 +milestone: '18.4' +group: group::global search +type: gitlab_com_derisk +default_enabled: false diff --git a/ee/lib/gitlab/elastic/client.rb b/ee/lib/gitlab/elastic/client.rb index 35c5faa0b6930b15d749b5e0eccaa372435beae0..27587b9b17557acfa127019e11d2da9199ae746f 100644 --- a/ee/lib/gitlab/elastic/client.rb +++ b/ee/lib/gitlab/elastic/client.rb @@ -31,6 +31,32 @@ def self.build(config) debug: debug? }.compact + if Feature.enabled?(:search_client_adapter_options, :instance) + base_config[:adapter_options] = { + # Connection pool limits to prevent accumulation + maxconnects: 10, # Max connections per ES host + max_total_connections: 50, # Total pool size across all hosts + + # Connection lifecycle management + timeout: config[:client_request_timeout], + connecttimeout: OPEN_TIMEOUT, + + # Connection cleanup settings + tcp_keepalive: 1, # Enable TCP keepalive + tcp_keepidle: 60, # Start keepalive after 60s idle + tcp_keepintvl: 30, # Keepalive probe interval + + # Force periodic connection refresh (prevents stale connections) + maxage: 300, # Max connection age (5 minutes) + + # Headers to assist with proper connection handling + httpheader: [ + 'Connection: keep-alive', + 'Keep-Alive: timeout=60, max=100' + ] + } + end + if config[:aws] creds = resolve_aws_credentials(config) region = config[:aws_region] diff --git a/ee/spec/lib/gitlab/elastic/client_spec.rb b/ee/spec/lib/gitlab/elastic/client_spec.rb index e7c2bfe7486862c51e0131d7aa17224e3b0ce176..f84c0dedd5d962c6cba126bd5bbd3e0cbaeb5e87 100644 --- a/ee/spec/lib/gitlab/elastic/client_spec.rb +++ b/ee/spec/lib/gitlab/elastic/client_spec.rb @@ -41,11 +41,29 @@ expect(client.transport.transport.options).to include(debug: true, log: true) end - context 'with typhoeus adapter for keep-alive connections' do - it 'sets typhoeus as the adapter' do + it 'sets typhoeus as the adapter' do + options = client.transport.transport.options + + expect(options).to include(adapter: :typhoeus) + end + + it 'sets adapter_options' do + options = client.transport.transport.options + + expect(options.keys).to include(:adapter_options) + expect(options[:adapter_options].keys).to match_array(%i[maxconnects max_total_connections + timeout connecttimeout tcp_keepalive tcp_keepidle tcp_keepintvl maxage httpheader]) + end + + context 'when search_client_adapter_options flag is false' do + before do + stub_feature_flags(search_client_adapter_options: false) + end + + it 'does not set adapter_options' do options = client.transport.transport.options - expect(options).to include(adapter: :typhoeus) + expect(options.keys).not_to include(:adapter_options) end end