diff --git a/contract-tests/client_entity.rb b/contract-tests/client_entity.rb index dc2043d4..99a177ba 100644 --- a/contract-tests/client_entity.rb +++ b/contract-tests/client_entity.rb @@ -15,11 +15,13 @@ def initialize(log, config) if config[:streaming] streaming = config[:streaming] opts[:stream_uri] = streaming[:baseUri] unless streaming[:baseUri].nil? + opts[:payload_filter_key] = streaming[:filter] unless streaming[:filter].nil? opts[:initial_reconnect_delay] = streaming[:initialRetryDelayMs] / 1_000.0 unless streaming[:initialRetryDelayMs].nil? elsif config[:polling] polling = config[:polling] opts[:stream] = false opts[:base_uri] = polling[:baseUri] unless polling[:baseUri].nil? + opts[:payload_filter_key] = polling[:filter] unless polling[:filter].nil? opts[:poll_interval] = polling[:pollIntervalMs] / 1_000.0 unless polling[:pollIntervalMs].nil? end diff --git a/contract-tests/service.rb b/contract-tests/service.rb index c542f6a2..853a63c1 100644 --- a/contract-tests/service.rb +++ b/contract-tests/service.rb @@ -30,6 +30,7 @@ 'all-flags-with-reasons', 'all-flags-client-side-only', 'all-flags-details-only-for-tracked-flags', + 'filtering', 'secure-mode-hash', 'user-type', 'tags', diff --git a/lib/ldclient-rb/config.rb b/lib/ldclient-rb/config.rb index 498d33d6..536e9019 100644 --- a/lib/ldclient-rb/config.rb +++ b/lib/ldclient-rb/config.rb @@ -57,6 +57,7 @@ class Config # @option opts [#open] :socket_factory See {#socket_factory}. # @option opts [BigSegmentsConfig] :big_segments See {#big_segments}. # @option opts [Hash] :application See {#application} + # @option opts [String] :payload_filter_key See {#payload_filter_key} # def initialize(opts = {}) @base_uri = (opts[:base_uri] || Config.default_base_uri).chomp("/") @@ -88,6 +89,7 @@ def initialize(opts = {}) @socket_factory = opts[:socket_factory] @big_segments = opts[:big_segments] || BigSegmentsConfig.new(store: nil) @application = LaunchDarkly::Impl::Util.validate_application_info(opts[:application] || {}, @logger) + @payload_filter_key = opts[:payload_filter_key] end # @@ -330,6 +332,21 @@ def offline? # attr_reader :application + # + # LaunchDarkly Server SDKs historically downloaded all flag configuration and segments for a particular environment + # during initialization. + # + # For some customers, this is an unacceptably large amount of data, and has contributed to performance issues within + # their products. + # + # Filtered environments aim to solve this problem. By allowing customers to specify subsets of an environment's + # flags using a filter key, SDKs will initialize faster and use less memory. + # + # This payload filter key only applies to the default streaming and polling data sources. It will not affect TestData or FileData + # data sources, nor will it be applied to any data source provided through the {#data_source} config property. + # + attr_reader :payload_filter_key + # # Set to true to opt out of sending diagnostics data. # diff --git a/lib/ldclient-rb/requestor.rb b/lib/ldclient-rb/requestor.rb index 58db38ab..c58ec81a 100644 --- a/lib/ldclient-rb/requestor.rb +++ b/lib/ldclient-rb/requestor.rb @@ -43,12 +43,10 @@ def stop private - def request_single_item(kind, path) - Impl::Model.deserialize(kind, make_request(path), @config.logger) - end - def make_request(path) - uri = URI(@config.base_uri + path) + uri = URI( + Util.add_payload_filter_key(@config.base_uri + path, @config) + ) headers = {} Impl::Util.default_http_headers(@sdk_key, @config).each { |k, v| headers[k] = v } headers["Connection"] = "keep-alive" diff --git a/lib/ldclient-rb/stream.rb b/lib/ldclient-rb/stream.rb index d6ab5086..6d8dd1bb 100644 --- a/lib/ldclient-rb/stream.rb +++ b/lib/ldclient-rb/stream.rb @@ -51,7 +51,9 @@ def start reconnect_time: @config.initial_reconnect_delay, } log_connection_started - @es = SSE::Client.new(@config.stream_uri + "/all", **opts) do |conn| + + uri = Util.add_payload_filter_key(@config.stream_uri + "/all", @config) + @es = SSE::Client.new(uri, **opts) do |conn| conn.on_event { |event| process_message(event) } conn.on_error { |err| log_connection_result(false) diff --git a/lib/ldclient-rb/util.rb b/lib/ldclient-rb/util.rb index df4ae191..5fcc23d4 100644 --- a/lib/ldclient-rb/util.rb +++ b/lib/ldclient-rb/util.rb @@ -4,6 +4,32 @@ module LaunchDarkly # @private module Util + # + # Append the payload filter key query parameter to the provided URI. + # + # @param uri [String] + # @param config [Config] + # @return [String] + # + def self.add_payload_filter_key(uri, config) + return uri if config.payload_filter_key.nil? + + unless config.payload_filter_key.is_a?(String) && !config.payload_filter_key.empty? + config.logger.warn { "[LDClient] Filter key must be a non-empty string. No filtering will be applied." } + return uri + end + + begin + parsed = URI.parse(uri) + new_query_params = URI.decode_www_form(String(parsed.query)) << ["filter", config.payload_filter_key] + parsed.query = URI.encode_www_form(new_query_params) + parsed.to_s + rescue URI::InvalidURIError + config.logger.warn { "[LDClient] URI could not be parsed. No filtering will be applied." } + uri + end + end + def self.new_http_client(uri_s, config) http_client_options = {} if config.socket_factory