From 708dcd2d7e271c67e6ecdd79be81f34eb10268be Mon Sep 17 00:00:00 2001 From: Matthew Keeler Date: Tue, 10 Nov 2026 14:48:58 -0500 Subject: [PATCH] feat: Use the top-level URI and HTTP options in the data source builders The polling, streaming and FDv1 fallback builders now take their base URI, socket factory, read timeout and connect timeout from Config when the builder does not set them. Config gets base_uri and stream_uri back as the default URIs for the polling and streaming data sources. A value set on a builder overrides the Config value. Before this change, the builders ignored the top-level read_timeout, connect_timeout and socket_factory, and a Relay Proxy user had to rebuild the default data system with DataSystem.custom to set the URIs. A v8 configuration that sets base_uri, stream_uri and events_uri for a Relay Proxy instance now works without change. --- lib/ldclient-rb/config.rb | 36 +++++++++ lib/ldclient-rb/data_system.rb | 12 +++ .../data_system/data_source_builder_common.rb | 32 +++++--- .../polling_data_source_builder.rb | 12 ++- .../streaming_data_source_builder.rb | 6 +- spec/config_spec.rb | 16 ++++ .../data_source_builder_common_spec.rb | 73 +++++++++++++++++++ .../data_system/streaming_headers_spec.rb | 11 +-- .../streaming_synchronizer_spec.rb | 11 +-- 9 files changed, 175 insertions(+), 34 deletions(-) create mode 100644 spec/data_system/data_source_builder_common_spec.rb diff --git a/lib/ldclient-rb/config.rb b/lib/ldclient-rb/config.rb index c324c02b..28d4b20c 100644 --- a/lib/ldclient-rb/config.rb +++ b/lib/ldclient-rb/config.rb @@ -18,6 +18,8 @@ class Config # # @param opts [Hash] the configuration options # @option opts [Logger] :logger See {#logger}. + # @option opts [String] :base_uri ("https://sdk.launchdarkly.com") See {#base_uri}. + # @option opts [String] :stream_uri ("https://stream.launchdarkly.com") See {#stream_uri}. # @option opts [String] :events_uri ("https://events.launchdarkly.com") See {#events_uri}. # @option opts [Integer] :capacity (10000) See {#capacity}. # @option opts [Float] :flush_interval (30) See {#flush_interval}. @@ -42,6 +44,8 @@ class Config # @option plugins [Array :base_uri, + FDv1PollingDataSourceBuilder => :base_uri, + StreamingDataSourceBuilder => :stream_uri, + }.each do |builder_class, uri_option| + RSpec.describe builder_class do + let(:socket_factory) { double("socket factory") } + + def http_config_of(builder, config) + http_config = nil + allow(Impl::DataSystem::HttpConfigOptions).to receive(:new).and_wrap_original do |original, **args| + http_config = original.call(**args) + end + builder.build("sdk-key", config) + http_config + end + + it "uses the default URI and HTTP options" do + config = Config.new(logger: $null_log) + http_config = http_config_of(described_class.new, config) + + expect(http_config.base_uri).to eq described_class::DEFAULT_BASE_URI + expect(http_config.socket_factory).to be_nil + expect(http_config.read_timeout).to eq Config.default_read_timeout + expect(http_config.connect_timeout).to eq Config.default_connect_timeout + end + + it "uses the URI and HTTP options from the SDK configuration" do + config = Config.new( + logger: $null_log, + uri_option => "https://relay.example.com/", + socket_factory: socket_factory, + read_timeout: 15, + connect_timeout: 4 + ) + http_config = http_config_of(described_class.new, config) + + expect(http_config.base_uri).to eq "https://relay.example.com" + expect(http_config.socket_factory).to be socket_factory + expect(http_config.read_timeout).to eq 15 + expect(http_config.connect_timeout).to eq 4 + end + + it "uses the builder settings in place of the SDK configuration" do + config = Config.new( + logger: $null_log, + uri_option => "https://relay.example.com", + socket_factory: double("config socket factory"), + read_timeout: 15, + connect_timeout: 4 + ) + builder = described_class.new + .base_uri("https://builder.example.com/") + .socket_factory(socket_factory) + .read_timeout(20) + .connect_timeout(6) + http_config = http_config_of(builder, config) + + expect(http_config.base_uri).to eq "https://builder.example.com" + expect(http_config.socket_factory).to be socket_factory + expect(http_config.read_timeout).to eq 20 + expect(http_config.connect_timeout).to eq 6 + end + end + end + end +end diff --git a/spec/impl/data_system/streaming_headers_spec.rb b/spec/impl/data_system/streaming_headers_spec.rb index 6da13874..42a0cc05 100644 --- a/spec/impl/data_system/streaming_headers_spec.rb +++ b/spec/impl/data_system/streaming_headers_spec.rb @@ -12,16 +12,7 @@ module DataSystem RSpec.describe "StreamingDataSource FDv1 fallback header detection" do let(:logger) { double("Logger", info: nil, warn: nil, error: nil, debug: nil) } let(:sdk_key) { "test-sdk-key" } - let(:config) do - double( - "Config", - logger: logger, - stream_uri: "https://stream.example.com", - socket_factory: nil, - initial_reconnect_delay: 1, - instance_id: nil - ) - end + let(:config) { LaunchDarkly::Config.new(logger: logger, stream_uri: "https://stream.example.com") } let(:synchronizer) { LaunchDarkly::DataSystem::StreamingDataSourceBuilder.new.build(sdk_key, config) } diff --git a/spec/impl/data_system/streaming_synchronizer_spec.rb b/spec/impl/data_system/streaming_synchronizer_spec.rb index 9eed6157..40f71be4 100644 --- a/spec/impl/data_system/streaming_synchronizer_spec.rb +++ b/spec/impl/data_system/streaming_synchronizer_spec.rb @@ -12,16 +12,7 @@ module DataSystem RSpec.describe StreamingDataSource do let(:logger) { double("Logger", info: nil, warn: nil, error: nil, debug: nil) } let(:sdk_key) { "test-sdk-key" } - let(:config) do - double( - "Config", - logger: logger, - stream_uri: "https://stream.example.com", - socket_factory: nil, - initial_reconnect_delay: 1, - instance_id: nil - ) - end + let(:config) { LaunchDarkly::Config.new(logger: logger, stream_uri: "https://stream.example.com") } # Mock SSE event class MockSSEEvent