Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 67 additions & 34 deletions contract-tests/client_entity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ def initialize(log, config)
polling = init_config[:polling]
next unless polling

opts[:base_uri] = polling[:baseUri] if polling[:baseUri]
set_optional_time_prop(polling, :pollIntervalMs, opts, :poll_interval)
initializers << LaunchDarkly::DataSystem.polling_ds_builder
initializers << build_polling_ds_builder(polling)
end
data_system.initializers(initializers)
end
Expand All @@ -44,41 +42,13 @@ def initialize(log, config)
primary = sync_config[:primary]
secondary = sync_config[:secondary]

primary_builder = nil
secondary_builder = nil

if primary
streaming = primary[:streaming]
if streaming
opts[:stream_uri] = streaming[:baseUri] if streaming[:baseUri]
set_optional_time_prop(streaming, :initialRetryDelayMs, opts, :initial_reconnect_delay)
primary_builder = LaunchDarkly::DataSystem.streaming_ds_builder
elsif primary[:polling]
polling = primary[:polling]
opts[:base_uri] = polling[:baseUri] if polling[:baseUri]
set_optional_time_prop(polling, :pollIntervalMs, opts, :poll_interval)
primary_builder = LaunchDarkly::DataSystem.polling_ds_builder
end
end

if secondary
streaming = secondary[:streaming]
if streaming
opts[:stream_uri] = streaming[:baseUri] if streaming[:baseUri]
set_optional_time_prop(streaming, :initialRetryDelayMs, opts, :initial_reconnect_delay)
secondary_builder = LaunchDarkly::DataSystem.streaming_ds_builder
elsif secondary[:polling]
polling = secondary[:polling]
opts[:base_uri] = polling[:baseUri] if polling[:baseUri]
set_optional_time_prop(polling, :pollIntervalMs, opts, :poll_interval)
secondary_builder = LaunchDarkly::DataSystem.polling_ds_builder
end
end
primary_builder = build_synchronizer_builder(primary)
secondary_builder = build_synchronizer_builder(secondary)

data_system.synchronizers(primary_builder, secondary_builder) if primary_builder

if primary_builder || secondary_builder
fallback_builder = LaunchDarkly::DataSystem.fdv1_fallback_ds_builder
fallback_builder = build_fdv1_fallback_builder(primary, secondary)
data_system.fdv1_compatible_synchronizer(fallback_builder)
end
end
Expand Down Expand Up @@ -313,6 +283,69 @@ def close
LaunchDarkly::LDContext.create(context)
end

#
# Builds a synchronizer builder from the contract test configuration.
#
# @param sync_config [Hash, nil] The synchronizer configuration (primary or secondary)
# @return [Object, nil] Returns the configured builder or nil
#
private def build_synchronizer_builder(sync_config)
return nil unless sync_config

streaming = sync_config[:streaming]
if streaming
build_streaming_ds_builder(streaming)
elsif sync_config[:polling]
build_polling_ds_builder(sync_config[:polling])
end
end

#
# Builds a streaming data source builder with the configured parameters.
#
# @param streaming_config [Hash] The streaming configuration
# @return [Object] Returns the configured streaming builder
#
private def build_streaming_ds_builder(streaming_config)
builder = LaunchDarkly::DataSystem.streaming_ds_builder
builder.base_uri(streaming_config[:baseUri]) if streaming_config[:baseUri]
builder.initial_reconnect_delay(streaming_config[:initialRetryDelayMs] / 1_000.0) if streaming_config[:initialRetryDelayMs]
builder
end

#
# Builds a polling data source builder with the configured parameters.
#
# @param polling_config [Hash] The polling configuration
# @return [Object] Returns the configured polling builder
#
private def build_polling_ds_builder(polling_config)
builder = LaunchDarkly::DataSystem.polling_ds_builder
builder.base_uri(polling_config[:baseUri]) if polling_config[:baseUri]
builder.poll_interval(polling_config[:pollIntervalMs] / 1_000.0) if polling_config[:pollIntervalMs]
builder
end

#
# Builds an FDv1 fallback polling data source builder using the first available config.
#
# @param primary [Hash, nil] The primary synchronizer configuration
# @param secondary [Hash, nil] The secondary synchronizer configuration
# @return [Object] Returns the configured FDv1 fallback builder
#
private def build_fdv1_fallback_builder(primary, secondary)
builder = LaunchDarkly::DataSystem.fdv1_fallback_ds_builder

# Use the first available polling config for the fallback base_uri
polling_config = primary&.dig(:polling) || secondary&.dig(:polling)
if polling_config
builder.base_uri(polling_config[:baseUri]) if polling_config[:baseUri]
builder.poll_interval(polling_config[:pollIntervalMs] / 1_000.0) if polling_config[:pollIntervalMs]
end

builder
end

#
# Builds a persistent data store from the contract test configuration.
#
Expand Down
41 changes: 22 additions & 19 deletions lib/ldclient-rb/config.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
require "logger"
require "ldclient-rb/impl/cache_store"
require "ldclient-rb/impl/data_system/http_config_options"
require "ldclient-rb/impl/data_system/polling"
require "ldclient-rb/impl/data_system/streaming"

module LaunchDarkly
#
Expand Down Expand Up @@ -465,15 +468,15 @@ def self.default_capacity
# @return [String] "https://sdk.launchdarkly.com"
#
def self.default_base_uri
"https://sdk.launchdarkly.com"
Impl::DataSystem::PollingDataSourceBuilder::DEFAULT_BASE_URI
end

#
# The default value for {#stream_uri}.
# @return [String] "https://stream.launchdarkly.com"
#
def self.default_stream_uri
"https://stream.launchdarkly.com"
Impl::DataSystem::StreamingDataSourceBuilder::DEFAULT_BASE_URI
end

#
Expand Down Expand Up @@ -505,23 +508,23 @@ def self.default_flush_interval
# @return [Float] 10
#
def self.default_read_timeout
10
Impl::DataSystem::HttpConfigOptions::DEFAULT_READ_TIMEOUT
end

#
# The default value for {#initial_reconnect_delay}.
# @return [Float] 1
#
def self.default_initial_reconnect_delay
1
Impl::DataSystem::StreamingDataSourceBuilder::DEFAULT_INITIAL_RECONNECT_DELAY
end

#
# The default value for {#connect_timeout}.
# @return [Float] 2
#
def self.default_connect_timeout
2
Impl::DataSystem::HttpConfigOptions::DEFAULT_CONNECT_TIMEOUT
end

#
Expand Down Expand Up @@ -575,7 +578,7 @@ def self.default_offline
# @return [Float] 30
#
def self.default_poll_interval
30
Impl::DataSystem::PollingDataSourceBuilder::DEFAULT_POLL_INTERVAL
end

#
Expand Down Expand Up @@ -699,13 +702,13 @@ def initialize(store:, context_cache_size: nil, context_cache_time: nil, status_
#
class DataSystemConfig
#
# @param initializers [Array<Proc(Config) => LaunchDarkly::Interfaces::DataSystem::Initializer>, nil] The (optional) array of builder procs
# @param primary_synchronizer [Proc(Config) => LaunchDarkly::Interfaces::DataSystem::Synchronizer, nil] The (optional) builder proc for primary synchronizer
# @param secondary_synchronizer [Proc(Config) => LaunchDarkly::Interfaces::DataSystem::Synchronizer, nil] The (optional) builder proc for secondary synchronizer
# @param initializers [Array<#build(String, Config)>, nil] The (optional) array of builders
# @param primary_synchronizer [#build(String, Config), nil] The (optional) builder for primary synchronizer
# @param secondary_synchronizer [#build(String, Config), nil] The (optional) builder for secondary synchronizer
# @param data_store_mode [Symbol] The (optional) data store mode
# @param data_store [LaunchDarkly::Interfaces::FeatureStore, nil] The (optional) data store
# @param fdv1_fallback_synchronizer [Proc(Config) => LaunchDarkly::Interfaces::DataSystem::Synchronizer, nil]
# The (optional) builder proc for FDv1-compatible fallback synchronizer
# @param fdv1_fallback_synchronizer [#build(String, Config), nil]
# The (optional) builder for FDv1-compatible fallback synchronizer
#
def initialize(initializers: nil, primary_synchronizer: nil, secondary_synchronizer: nil,
data_store_mode: LaunchDarkly::Interfaces::DataSystem::DataStoreMode::READ_ONLY, data_store: nil, fdv1_fallback_synchronizer: nil)
Expand All @@ -717,16 +720,16 @@ def initialize(initializers: nil, primary_synchronizer: nil, secondary_synchroni
@fdv1_fallback_synchronizer = fdv1_fallback_synchronizer
end

# The initializers for the data system. Each proc takes sdk_key and Config and returns an Initializer.
# @return [Array<Proc(String, Config) => LaunchDarkly::Interfaces::DataSystem::Initializer>, nil]
# The initializers for the data system. Each builder responds to build(sdk_key, config) and returns an Initializer.
# @return [Array<#build(String, Config)>, nil]
attr_reader :initializers

# The primary synchronizer builder. Takes sdk_key and Config and returns a Synchronizer.
# @return [Proc(String, Config) => LaunchDarkly::Interfaces::DataSystem::Synchronizer, nil]
# The primary synchronizer builder. Responds to build(sdk_key, config) and returns a Synchronizer.
# @return [#build(String, Config), nil]
attr_reader :primary_synchronizer

# The secondary synchronizer builder. Takes sdk_key and Config and returns a Synchronizer.
# @return [Proc(String, Config) => LaunchDarkly::Interfaces::DataSystem::Synchronizer, nil]
# The secondary synchronizer builder. Responds to build(sdk_key, config) and returns a Synchronizer.
# @return [#build(String, Config), nil]
attr_reader :secondary_synchronizer

# The data store mode.
Expand All @@ -737,8 +740,8 @@ def initialize(initializers: nil, primary_synchronizer: nil, secondary_synchroni
# @return [LaunchDarkly::Interfaces::FeatureStore, nil]
attr_reader :data_store

# The FDv1-compatible fallback synchronizer builder. Takes sdk_key and Config and returns a Synchronizer.
# @return [Proc(String, Config) => LaunchDarkly::Interfaces::DataSystem::Synchronizer, nil]
# The FDv1-compatible fallback synchronizer builder. Responds to build(sdk_key, config) and returns a Synchronizer.
# @return [#build(String, Config), nil]
attr_reader :fdv1_fallback_synchronizer
end
end
36 changes: 14 additions & 22 deletions lib/ldclient-rb/data_system.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ def initialize
#
# Sets the initializers for the data system.
#
# @param initializers [Array<Proc(String, Config) => LaunchDarkly::Interfaces::DataSystem::Initializer>]
# Array of builder procs that take sdk_key and Config and return an Initializer
# @param initializers [Array<#build(String, Config)>]
# Array of builders that respond to build(sdk_key, config) and return an Initializer
# @return [ConfigBuilder] self for chaining
#
def initializers(initializers)
Expand All @@ -40,9 +40,8 @@ def initializers(initializers)
#
# Sets the synchronizers for the data system.
#
# @param primary [Proc(String, Config) => LaunchDarkly::Interfaces::DataSystem::Synchronizer] Builder proc that takes sdk_key and Config and returns the primary Synchronizer
# @param secondary [Proc(String, Config) => LaunchDarkly::Interfaces::DataSystem::Synchronizer, nil]
# Builder proc that takes sdk_key and Config and returns the secondary Synchronizer
# @param primary [#build(String, Config)] Builder that responds to build(sdk_key, config) and returns the primary Synchronizer
# @param secondary [#build(String, Config), nil] Builder that responds to build(sdk_key, config) and returns the secondary Synchronizer
# @return [ConfigBuilder] self for chaining
#
def synchronizers(primary, secondary = nil)
Expand All @@ -55,8 +54,7 @@ def synchronizers(primary, secondary = nil)
# Configures the SDK with a fallback synchronizer that is compatible with
# the Flag Delivery v1 API.
#
# @param fallback [Proc(String, Config) => LaunchDarkly::Interfaces::DataSystem::Synchronizer]
# Builder proc that takes sdk_key and Config and returns the fallback Synchronizer
# @param fallback [#build(String, Config)] Builder that responds to build(sdk_key, config) and returns the fallback Synchronizer
# @return [ConfigBuilder] self for chaining
#
def fdv1_compatible_synchronizer(fallback)
Expand Down Expand Up @@ -100,42 +98,36 @@ def build
end

#
# Returns a builder proc for creating a polling data source.
# Returns a builder for creating a polling data source.
# This is a building block that can be used with {ConfigBuilder#initializers}
# or {ConfigBuilder#synchronizers} to create custom data system configurations.
#
# @return [Proc] A proc that takes (sdk_key, config) and returns a polling data source
# @return [LaunchDarkly::Impl::DataSystem::PollingDataSourceBuilder]
#
def self.polling_ds_builder
lambda do |sdk_key, config|
LaunchDarkly::Impl::DataSystem::PollingDataSourceBuilder.new(sdk_key, config).build
end
LaunchDarkly::Impl::DataSystem::PollingDataSourceBuilder.new
end

#
# Returns a builder proc for creating an FDv1 fallback polling data source.
# Returns a builder for creating an FDv1 fallback polling data source.
# This is a building block that can be used with {ConfigBuilder#fdv1_compatible_synchronizer}
# to provide FDv1 compatibility in custom data system configurations.
#
# @return [Proc] A proc that takes (sdk_key, config) and returns an FDv1 polling data source
# @return [LaunchDarkly::Impl::DataSystem::FDv1PollingDataSourceBuilder]
#
def self.fdv1_fallback_ds_builder
lambda do |sdk_key, config|
LaunchDarkly::Impl::DataSystem::FDv1PollingDataSourceBuilder.new(sdk_key, config).build
end
LaunchDarkly::Impl::DataSystem::FDv1PollingDataSourceBuilder.new
end

#
# Returns a builder proc for creating a streaming data source.
# Returns a builder for creating a streaming data source.
# This is a building block that can be used with {ConfigBuilder#synchronizers}
# to create custom data system configurations.
#
# @return [Proc] A proc that takes (sdk_key, config) and returns a streaming data source
# @return [LaunchDarkly::Impl::DataSystem::StreamingDataSourceBuilder]
#
def self.streaming_ds_builder
lambda do |sdk_key, config|
LaunchDarkly::Impl::DataSystem::StreamingDataSourceBuilder.new(sdk_key, config).build
end
LaunchDarkly::Impl::DataSystem::StreamingDataSourceBuilder.new
end

#
Expand Down
2 changes: 1 addition & 1 deletion lib/ldclient-rb/events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def initialize(sdk_key, config, client = nil, diagnostic_accumulator = nil, test
@inbox_full = Concurrent::AtomicBoolean.new(false)

event_sender = (test_properties || {})[:event_sender] ||
Impl::EventSender.new(sdk_key, config, client || Impl::Util.new_http_client(config.events_uri, config))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing this line has made the client parameter unused. Were we ever providing this and are we appropriately capturing that level of control that we previously had?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The client was actually unused in the EventSender initializer and it just constructed its own client.

Impl::EventSender.new(sdk_key, config)

@timestamp_fn = (test_properties || {})[:timestamp_fn] || proc { Impl::Util.current_time_millis }
@omit_anonymous_contexts = config.omit_anonymous_contexts
Expand Down
11 changes: 9 additions & 2 deletions lib/ldclient-rb/impl/data_source/requestor.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "ldclient-rb/impl/model/serialization"
require "ldclient-rb/impl/util"
require "ldclient-rb/impl/data_system/http_config_options"

require "concurrent/atomics"
require "json"
Expand All @@ -26,7 +27,13 @@ class Requestor
def initialize(sdk_key, config)
@sdk_key = sdk_key
@config = config
@http_client = Impl::Util.new_http_client(config.base_uri, config)
@http_config = DataSystem::HttpConfigOptions.new(
base_uri: config.base_uri,
socket_factory: config.socket_factory,
read_timeout: config.read_timeout,
connect_timeout: config.connect_timeout
)
@http_client = Impl::Util.new_http_client(@http_config)
.use(:auto_inflate)
.headers("Accept-Encoding" => "gzip")
@cache = @config.cache_store
Expand All @@ -48,7 +55,7 @@ def stop

def make_request(path)
uri = URI(
Util.add_payload_filter_key(@config.base_uri + path, @config)
Util.add_payload_filter_key(@http_config.base_uri + path, @config)
)
headers = {}
Impl::Util.default_http_headers(@sdk_key, @config).each { |k, v| headers[k] = v }
Expand Down
Loading