launchdarkly-server-sdk 8.11.2 → 8.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ldclient-rb/config.rb +66 -3
- data/lib/ldclient-rb/context.rb +1 -1
- data/lib/ldclient-rb/data_system.rb +243 -0
- data/lib/ldclient-rb/events.rb +34 -19
- data/lib/ldclient-rb/flags_state.rb +1 -1
- data/lib/ldclient-rb/impl/big_segments.rb +4 -4
- data/lib/ldclient-rb/impl/cache_store.rb +44 -0
- data/lib/ldclient-rb/impl/data_source/polling.rb +108 -0
- data/lib/ldclient-rb/impl/data_source/requestor.rb +106 -0
- data/lib/ldclient-rb/impl/data_source/status_provider.rb +78 -0
- data/lib/ldclient-rb/impl/data_source/stream.rb +198 -0
- data/lib/ldclient-rb/impl/data_source.rb +3 -3
- data/lib/ldclient-rb/impl/data_store/data_kind.rb +108 -0
- data/lib/ldclient-rb/impl/data_store/feature_store_client_wrapper.rb +187 -0
- data/lib/ldclient-rb/impl/data_store/in_memory_feature_store.rb +130 -0
- data/lib/ldclient-rb/impl/data_store/status_provider.rb +82 -0
- data/lib/ldclient-rb/impl/data_store/store.rb +371 -0
- data/lib/ldclient-rb/impl/data_store.rb +11 -97
- data/lib/ldclient-rb/impl/data_system/fdv1.rb +20 -7
- data/lib/ldclient-rb/impl/data_system/fdv2.rb +471 -0
- data/lib/ldclient-rb/impl/data_system/polling.rb +601 -0
- data/lib/ldclient-rb/impl/data_system/protocolv2.rb +264 -0
- data/lib/ldclient-rb/impl/dependency_tracker.rb +21 -9
- data/lib/ldclient-rb/impl/evaluator.rb +3 -2
- data/lib/ldclient-rb/impl/event_sender.rb +4 -3
- data/lib/ldclient-rb/impl/expiring_cache.rb +79 -0
- data/lib/ldclient-rb/impl/integrations/file_data_source.rb +8 -8
- data/lib/ldclient-rb/impl/integrations/test_data/test_data_source_v2.rb +288 -0
- data/lib/ldclient-rb/impl/memoized_value.rb +34 -0
- data/lib/ldclient-rb/impl/migrations/migrator.rb +2 -1
- data/lib/ldclient-rb/impl/migrations/tracker.rb +2 -1
- data/lib/ldclient-rb/impl/model/serialization.rb +6 -6
- data/lib/ldclient-rb/impl/non_blocking_thread_pool.rb +48 -0
- data/lib/ldclient-rb/impl/repeating_task.rb +2 -2
- data/lib/ldclient-rb/impl/simple_lru_cache.rb +27 -0
- data/lib/ldclient-rb/impl/util.rb +65 -0
- data/lib/ldclient-rb/impl.rb +1 -2
- data/lib/ldclient-rb/in_memory_store.rb +1 -18
- data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +9 -9
- data/lib/ldclient-rb/integrations/test_data.rb +11 -11
- data/lib/ldclient-rb/integrations/test_data_v2/flag_builder_v2.rb +582 -0
- data/lib/ldclient-rb/integrations/test_data_v2.rb +248 -0
- data/lib/ldclient-rb/integrations/util/store_wrapper.rb +3 -2
- data/lib/ldclient-rb/interfaces/data_system.rb +755 -0
- data/lib/ldclient-rb/interfaces/feature_store.rb +3 -0
- data/lib/ldclient-rb/ldclient.rb +55 -131
- data/lib/ldclient-rb/util.rb +11 -70
- data/lib/ldclient-rb/version.rb +1 -1
- data/lib/ldclient-rb.rb +8 -17
- metadata +35 -17
- data/lib/ldclient-rb/cache_store.rb +0 -45
- data/lib/ldclient-rb/expiring_cache.rb +0 -77
- data/lib/ldclient-rb/memoized_value.rb +0 -32
- data/lib/ldclient-rb/non_blocking_thread_pool.rb +0 -46
- data/lib/ldclient-rb/polling.rb +0 -102
- data/lib/ldclient-rb/requestor.rb +0 -102
- data/lib/ldclient-rb/simple_lru_cache.rb +0 -25
- data/lib/ldclient-rb/stream.rb +0 -197
|
@@ -103,6 +103,9 @@ module LaunchDarkly
|
|
|
103
103
|
#
|
|
104
104
|
# Performs any necessary cleanup to shut down the store when the client is being shut down.
|
|
105
105
|
#
|
|
106
|
+
# This method should be idempotent - it is safe to call it multiple times, and subsequent
|
|
107
|
+
# calls after the first should have no effect.
|
|
108
|
+
#
|
|
106
109
|
# @return [void]
|
|
107
110
|
#
|
|
108
111
|
def stop
|
data/lib/ldclient-rb/ldclient.rb
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
require "ldclient-rb/impl/big_segments"
|
|
2
2
|
require "ldclient-rb/impl/broadcaster"
|
|
3
|
+
require "ldclient-rb/impl/context"
|
|
3
4
|
require "ldclient-rb/impl/data_source"
|
|
4
5
|
require "ldclient-rb/impl/data_store"
|
|
5
|
-
require "ldclient-rb/impl/
|
|
6
|
+
require "ldclient-rb/impl/data_system/fdv1"
|
|
6
7
|
require "ldclient-rb/impl/diagnostic_events"
|
|
7
|
-
require "ldclient-rb/impl/evaluator"
|
|
8
8
|
require "ldclient-rb/impl/evaluation_with_hook_result"
|
|
9
|
+
require "ldclient-rb/impl/evaluator"
|
|
9
10
|
require "ldclient-rb/impl/flag_tracker"
|
|
10
|
-
require "ldclient-rb/impl/store_client_wrapper"
|
|
11
11
|
require "ldclient-rb/impl/migrations/tracker"
|
|
12
|
+
require "ldclient-rb/impl/util"
|
|
13
|
+
require "ldclient-rb/events"
|
|
12
14
|
require "concurrent"
|
|
13
15
|
require "concurrent/atomics"
|
|
14
16
|
require "digest/sha1"
|
|
@@ -30,6 +32,18 @@ module LaunchDarkly
|
|
|
30
32
|
|
|
31
33
|
def_delegators :@config, :logger
|
|
32
34
|
|
|
35
|
+
# @!method flush
|
|
36
|
+
# Delegates to {LaunchDarkly::EventProcessorMethods#flush}.
|
|
37
|
+
def_delegator :@event_processor, :flush
|
|
38
|
+
|
|
39
|
+
# @!method data_store_status_provider
|
|
40
|
+
# Delegates to the data system {LaunchDarkly::Impl::DataSystem#data_store_status_provider}.
|
|
41
|
+
# @return [LaunchDarkly::Interfaces::DataStore::StatusProvider]
|
|
42
|
+
# @!method data_source_status_provider
|
|
43
|
+
# Delegates to the data system {LaunchDarkly::Impl::DataSystem#data_source_status_provider}.
|
|
44
|
+
# @return [LaunchDarkly::Interfaces::DataSource::StatusProvider]
|
|
45
|
+
def_delegators :@data_system, :data_store_status_provider, :data_source_status_provider
|
|
46
|
+
|
|
33
47
|
#
|
|
34
48
|
# Creates a new client instance that connects to LaunchDarkly. A custom
|
|
35
49
|
# configuration parameter can also supplied to specify advanced options,
|
|
@@ -48,13 +62,16 @@ module LaunchDarkly
|
|
|
48
62
|
#
|
|
49
63
|
def initialize(sdk_key, config = Config.default, wait_for_sec = 5)
|
|
50
64
|
# Note that sdk_key is normally a required parameter, and a nil value would cause the SDK to
|
|
51
|
-
# fail in most configurations. However, there are some configurations where it would be OK
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
if !config.offline? &&
|
|
57
|
-
|
|
65
|
+
# fail in most configurations. However, there are some configurations where it would be OK to
|
|
66
|
+
# not provide a SDK key.
|
|
67
|
+
# * Offline mode
|
|
68
|
+
# * Using LDD mode with events disabled
|
|
69
|
+
# * Using a custom data source (like FileData) with events disabled
|
|
70
|
+
if !config.offline? && sdk_key.nil?
|
|
71
|
+
# If the data source is nil we create a default data source which requires the SDK key.
|
|
72
|
+
if config.send_events || (!config.use_ldd? && config.data_source.nil?)
|
|
73
|
+
raise ArgumentError, "sdk_key must not be nil"
|
|
74
|
+
end
|
|
58
75
|
end
|
|
59
76
|
|
|
60
77
|
@sdk_key = sdk_key
|
|
@@ -82,9 +99,10 @@ module LaunchDarkly
|
|
|
82
99
|
# @param wait_for_sec [Float] maximum time (in seconds) to wait for initialization
|
|
83
100
|
#
|
|
84
101
|
def postfork(wait_for_sec = 5)
|
|
85
|
-
@
|
|
102
|
+
@data_system = nil
|
|
86
103
|
@event_processor = nil
|
|
87
104
|
@big_segment_store_manager = nil
|
|
105
|
+
@flag_tracker = nil
|
|
88
106
|
|
|
89
107
|
start_up(wait_for_sec)
|
|
90
108
|
end
|
|
@@ -95,32 +113,22 @@ module LaunchDarkly
|
|
|
95
113
|
|
|
96
114
|
@hooks = Concurrent::Array.new(@config.hooks + plugin_hooks)
|
|
97
115
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
store_sink = LaunchDarkly::Impl::DataStore::UpdateSink.new(data_store_broadcaster)
|
|
102
|
-
|
|
103
|
-
# We need to wrap the feature store object with a FeatureStoreClientWrapper in order to add
|
|
104
|
-
# some necessary logic around updates. Unfortunately, we have code elsewhere that accesses
|
|
105
|
-
# the feature store through the Config object, so we need to make a new Config that uses
|
|
106
|
-
# the wrapped store.
|
|
107
|
-
@store = Impl::FeatureStoreClientWrapper.new(@config.feature_store, store_sink, @config.logger)
|
|
108
|
-
updated_config = @config.clone
|
|
109
|
-
updated_config.instance_variable_set(:@feature_store, @store)
|
|
110
|
-
@config = updated_config
|
|
111
|
-
|
|
112
|
-
@data_store_status_provider = LaunchDarkly::Impl::DataStore::StatusProvider.new(@store, store_sink)
|
|
116
|
+
# Initialize the data system (FDv1 for now, will support FDv2 in the future)
|
|
117
|
+
# Note: FDv1 will update @config.feature_store to use its wrapped store
|
|
118
|
+
@data_system = Impl::DataSystem::FDv1.new(@sdk_key, @config)
|
|
113
119
|
|
|
120
|
+
# Components not managed by data system
|
|
114
121
|
@big_segment_store_manager = Impl::BigSegmentStoreManager.new(@config.big_segments, @config.logger)
|
|
115
122
|
@big_segment_store_status_provider = @big_segment_store_manager.status_provider
|
|
116
123
|
|
|
117
|
-
get_flag = lambda { |key| @store.get(FEATURES, key) }
|
|
118
|
-
get_segment = lambda { |key| @store.get(SEGMENTS, key) }
|
|
124
|
+
get_flag = lambda { |key| @data_system.store.get(Impl::DataStore::FEATURES, key) }
|
|
125
|
+
get_segment = lambda { |key| @data_system.store.get(Impl::DataStore::SEGMENTS, key) }
|
|
119
126
|
get_big_segments_membership = lambda { |key| @big_segment_store_manager.get_context_membership(key) }
|
|
120
127
|
@evaluator = LaunchDarkly::Impl::Evaluator.new(get_flag, get_segment, get_big_segments_membership, @config.logger)
|
|
121
128
|
|
|
122
129
|
if !@config.offline? && @config.send_events && !@config.diagnostic_opt_out?
|
|
123
130
|
diagnostic_accumulator = Impl::DiagnosticAccumulator.new(Impl::DiagnosticAccumulator.create_diagnostic_id(@sdk_key))
|
|
131
|
+
@data_system.set_diagnostic_accumulator(diagnostic_accumulator)
|
|
124
132
|
else
|
|
125
133
|
diagnostic_accumulator = nil
|
|
126
134
|
end
|
|
@@ -131,38 +139,14 @@ module LaunchDarkly
|
|
|
131
139
|
@event_processor = EventProcessor.new(@sdk_key, @config, nil, diagnostic_accumulator)
|
|
132
140
|
end
|
|
133
141
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
return # requestor and update processor are not used in this mode
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
flag_tracker_broadcaster = LaunchDarkly::Impl::Broadcaster.new(@shared_executor, @config.logger)
|
|
141
|
-
@flag_tracker = LaunchDarkly::Impl::FlagTracker.new(flag_tracker_broadcaster, lambda { |key, context| variation(key, context, nil) })
|
|
142
|
-
|
|
143
|
-
data_source_broadcaster = LaunchDarkly::Impl::Broadcaster.new(@shared_executor, @config.logger)
|
|
144
|
-
|
|
145
|
-
# Make the update sink available on the config so that our data source factory can access the sink with a shared executor.
|
|
146
|
-
@config.data_source_update_sink = LaunchDarkly::Impl::DataSource::UpdateSink.new(@store, data_source_broadcaster, flag_tracker_broadcaster)
|
|
147
|
-
|
|
148
|
-
@data_source_status_provider = LaunchDarkly::Impl::DataSource::StatusProvider.new(data_source_broadcaster, @config.data_source_update_sink)
|
|
149
|
-
|
|
150
|
-
data_source_or_factory = @config.data_source || self.method(:create_default_data_source)
|
|
151
|
-
if data_source_or_factory.respond_to? :call
|
|
152
|
-
# Currently, data source factories take two parameters unless they need to be aware of diagnostic_accumulator, in
|
|
153
|
-
# which case they take three parameters. This will be changed in the future to use a less awkware mechanism.
|
|
154
|
-
if data_source_or_factory.arity == 3
|
|
155
|
-
@data_source = data_source_or_factory.call(@sdk_key, @config, diagnostic_accumulator)
|
|
156
|
-
else
|
|
157
|
-
@data_source = data_source_or_factory.call(@sdk_key, @config)
|
|
158
|
-
end
|
|
159
|
-
else
|
|
160
|
-
@data_source = data_source_or_factory
|
|
161
|
-
end
|
|
142
|
+
# Create the flag tracker using the broadcaster from the data system
|
|
143
|
+
eval_fn = lambda { |key, context| variation(key, context, nil) }
|
|
144
|
+
@flag_tracker = Impl::FlagTracker.new(@data_system.flag_change_broadcaster, eval_fn)
|
|
162
145
|
|
|
163
146
|
register_plugins(environment_metadata)
|
|
164
147
|
|
|
165
|
-
|
|
148
|
+
# Start the data system
|
|
149
|
+
ready = @data_system.start
|
|
166
150
|
|
|
167
151
|
return unless wait_for_sec > 0
|
|
168
152
|
|
|
@@ -173,7 +157,7 @@ module LaunchDarkly
|
|
|
173
157
|
ok = ready.wait(wait_for_sec)
|
|
174
158
|
if !ok
|
|
175
159
|
@config.logger.error { "[LDClient] Timeout encountered waiting for LaunchDarkly client initialization" }
|
|
176
|
-
elsif
|
|
160
|
+
elsif !initialized?
|
|
177
161
|
@config.logger.error { "[LDClient] LaunchDarkly client initialization failed" }
|
|
178
162
|
end
|
|
179
163
|
end
|
|
@@ -236,22 +220,6 @@ module LaunchDarkly
|
|
|
236
220
|
@hooks.push(hook)
|
|
237
221
|
end
|
|
238
222
|
|
|
239
|
-
#
|
|
240
|
-
# Tells the client that all pending analytics events should be delivered as soon as possible.
|
|
241
|
-
#
|
|
242
|
-
# When the LaunchDarkly client generates analytics events (from {#variation}, {#variation_detail},
|
|
243
|
-
# {#identify}, or {#track}), they are queued on a worker thread. The event thread normally
|
|
244
|
-
# sends all queued events to LaunchDarkly at regular intervals, controlled by the
|
|
245
|
-
# {Config#flush_interval} option. Calling `flush` triggers a send without waiting for the
|
|
246
|
-
# next interval.
|
|
247
|
-
#
|
|
248
|
-
# Flushing is asynchronous, so this method will return before it is complete. However, if you
|
|
249
|
-
# call {#close}, events are guaranteed to be sent before that method returns.
|
|
250
|
-
#
|
|
251
|
-
def flush
|
|
252
|
-
@event_processor.flush
|
|
253
|
-
end
|
|
254
|
-
|
|
255
223
|
#
|
|
256
224
|
# Creates a hash string that can be used by the JavaScript SDK to identify a context.
|
|
257
225
|
# For more information, see [Secure mode](https://docs.launchdarkly.com/sdk/features/secure-mode#ruby).
|
|
@@ -288,7 +256,7 @@ module LaunchDarkly
|
|
|
288
256
|
# @return [Boolean] true if the client has been initialized
|
|
289
257
|
#
|
|
290
258
|
def initialized?
|
|
291
|
-
@
|
|
259
|
+
@data_system.data_availability == @data_system.target_availability
|
|
292
260
|
end
|
|
293
261
|
|
|
294
262
|
#
|
|
@@ -594,7 +562,7 @@ module LaunchDarkly
|
|
|
594
562
|
return FeatureFlagsState.new(false) if @config.offline?
|
|
595
563
|
|
|
596
564
|
unless initialized?
|
|
597
|
-
if @store.initialized?
|
|
565
|
+
if @data_system.store.initialized?
|
|
598
566
|
@config.logger.warn { "Called all_flags_state before client initialization; using last known values from data store" }
|
|
599
567
|
else
|
|
600
568
|
@config.logger.warn { "Called all_flags_state before client initialization. Data store not available; returning empty state" }
|
|
@@ -609,9 +577,9 @@ module LaunchDarkly
|
|
|
609
577
|
end
|
|
610
578
|
|
|
611
579
|
begin
|
|
612
|
-
features = @store.all(FEATURES)
|
|
580
|
+
features = @data_system.store.all(Impl::DataStore::FEATURES)
|
|
613
581
|
rescue => exn
|
|
614
|
-
Util.log_exception(@config.logger, "Unable to read flags for all_flags_state", exn)
|
|
582
|
+
Impl::Util.log_exception(@config.logger, "Unable to read flags for all_flags_state", exn)
|
|
615
583
|
return FeatureFlagsState.new(false)
|
|
616
584
|
end
|
|
617
585
|
|
|
@@ -628,7 +596,7 @@ module LaunchDarkly
|
|
|
628
596
|
detail = eval_result.detail
|
|
629
597
|
rescue => exn
|
|
630
598
|
detail = EvaluationDetail.new(nil, nil, EvaluationReason::error(EvaluationReason::ERROR_EXCEPTION))
|
|
631
|
-
Util.log_exception(@config.logger, "Error evaluating flag \"#{k}\" in all_flags_state", exn)
|
|
599
|
+
Impl::Util.log_exception(@config.logger, "Error evaluating flag \"#{k}\" in all_flags_state", exn)
|
|
632
600
|
end
|
|
633
601
|
|
|
634
602
|
requires_experiment_data = experiment?(f, detail.reason)
|
|
@@ -656,11 +624,9 @@ module LaunchDarkly
|
|
|
656
624
|
# @return [void]
|
|
657
625
|
def close
|
|
658
626
|
@config.logger.info { "[LDClient] Closing LaunchDarkly client..." }
|
|
659
|
-
@
|
|
627
|
+
@data_system.stop
|
|
660
628
|
@event_processor.stop
|
|
661
629
|
@big_segment_store_manager.stop
|
|
662
|
-
@store.stop
|
|
663
|
-
@shared_executor.shutdown
|
|
664
630
|
end
|
|
665
631
|
|
|
666
632
|
#
|
|
@@ -671,33 +637,6 @@ module LaunchDarkly
|
|
|
671
637
|
#
|
|
672
638
|
attr_reader :big_segment_store_status_provider
|
|
673
639
|
|
|
674
|
-
#
|
|
675
|
-
# Returns an interface for tracking the status of a persistent data store.
|
|
676
|
-
#
|
|
677
|
-
# The {LaunchDarkly::Interfaces::DataStore::StatusProvider} has methods for
|
|
678
|
-
# checking whether the data store is (as far as the SDK knows) currently
|
|
679
|
-
# operational, tracking changes in this status, and getting cache
|
|
680
|
-
# statistics. These are only relevant for a persistent data store; if you
|
|
681
|
-
# are using an in-memory data store, then this method will return a stub
|
|
682
|
-
# object that provides no information.
|
|
683
|
-
#
|
|
684
|
-
# @return [LaunchDarkly::Interfaces::DataStore::StatusProvider]
|
|
685
|
-
#
|
|
686
|
-
attr_reader :data_store_status_provider
|
|
687
|
-
|
|
688
|
-
#
|
|
689
|
-
# Returns an interface for tracking the status of the data source.
|
|
690
|
-
#
|
|
691
|
-
# The data source is the mechanism that the SDK uses to get feature flag
|
|
692
|
-
# configurations, such as a streaming connection (the default) or poll
|
|
693
|
-
# requests. The {LaunchDarkly::Interfaces::DataSource::StatusProvider} has
|
|
694
|
-
# methods for checking whether the data source is (as far as the SDK knows)
|
|
695
|
-
# currently operational and tracking changes in this status.
|
|
696
|
-
#
|
|
697
|
-
# @return [LaunchDarkly::Interfaces::DataSource::StatusProvider]
|
|
698
|
-
#
|
|
699
|
-
attr_reader :data_source_status_provider
|
|
700
|
-
|
|
701
640
|
#
|
|
702
641
|
# Returns an interface for tracking changes in feature flag configurations.
|
|
703
642
|
#
|
|
@@ -705,23 +644,8 @@ module LaunchDarkly
|
|
|
705
644
|
# requesting notifications about feature flag changes using an event
|
|
706
645
|
# listener model.
|
|
707
646
|
#
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
private
|
|
711
|
-
|
|
712
|
-
def create_default_data_source(sdk_key, config, diagnostic_accumulator)
|
|
713
|
-
if config.offline?
|
|
714
|
-
return LaunchDarkly::Impl::DataSource::NullUpdateProcessor.new
|
|
715
|
-
end
|
|
716
|
-
raise ArgumentError, "sdk_key must not be nil" if sdk_key.nil? # see LDClient constructor comment on sdk_key
|
|
717
|
-
if config.stream?
|
|
718
|
-
StreamProcessor.new(sdk_key, config, diagnostic_accumulator)
|
|
719
|
-
else
|
|
720
|
-
config.logger.info { "Disabling streaming API" }
|
|
721
|
-
config.logger.warn { "You should only disable the streaming API if instructed to do so by LaunchDarkly support" }
|
|
722
|
-
requestor = Requestor.new(sdk_key, config)
|
|
723
|
-
PollingProcessor.new(config, requestor)
|
|
724
|
-
end
|
|
647
|
+
def flag_tracker
|
|
648
|
+
@flag_tracker
|
|
725
649
|
end
|
|
726
650
|
|
|
727
651
|
#
|
|
@@ -731,7 +655,7 @@ module LaunchDarkly
|
|
|
731
655
|
#
|
|
732
656
|
# @return [Array<EvaluationDetail, [LaunchDarkly::Impl::Model::FeatureFlag, nil], [String, nil]>]
|
|
733
657
|
#
|
|
734
|
-
def variation_with_flag(key, context, default)
|
|
658
|
+
private def variation_with_flag(key, context, default)
|
|
735
659
|
evaluate_internal(key, context, default, false)
|
|
736
660
|
end
|
|
737
661
|
|
|
@@ -743,7 +667,7 @@ module LaunchDarkly
|
|
|
743
667
|
#
|
|
744
668
|
# @return [Array<EvaluationDetail, [LaunchDarkly::Impl::Model::FeatureFlag, nil], [String, nil]>]
|
|
745
669
|
#
|
|
746
|
-
def evaluate_internal(key, context, default, with_reasons)
|
|
670
|
+
private def evaluate_internal(key, context, default, with_reasons)
|
|
747
671
|
if @config.offline?
|
|
748
672
|
return Evaluator.error_result(EvaluationReason::ERROR_CLIENT_NOT_READY, default), nil, nil
|
|
749
673
|
end
|
|
@@ -761,7 +685,7 @@ module LaunchDarkly
|
|
|
761
685
|
end
|
|
762
686
|
|
|
763
687
|
unless initialized?
|
|
764
|
-
if @store.initialized?
|
|
688
|
+
if @data_system.store.initialized?
|
|
765
689
|
@config.logger.warn { "[LDClient] Client has not finished initializing; using last known values from feature store" }
|
|
766
690
|
else
|
|
767
691
|
@config.logger.error { "[LDClient] Client has not finished initializing; feature store unavailable, returning default value" }
|
|
@@ -772,7 +696,7 @@ module LaunchDarkly
|
|
|
772
696
|
end
|
|
773
697
|
|
|
774
698
|
begin
|
|
775
|
-
feature = @store.get(FEATURES, key)
|
|
699
|
+
feature = @data_system.store.get(Impl::DataStore::FEATURES, key)
|
|
776
700
|
rescue
|
|
777
701
|
# Ignored
|
|
778
702
|
end
|
|
@@ -798,7 +722,7 @@ module LaunchDarkly
|
|
|
798
722
|
record_flag_eval(feature, context, detail, default, with_reasons)
|
|
799
723
|
[detail, feature, nil]
|
|
800
724
|
rescue => exn
|
|
801
|
-
Util.log_exception(@config.logger, "Error evaluating feature flag \"#{key}\"", exn)
|
|
725
|
+
Impl::Util.log_exception(@config.logger, "Error evaluating feature flag \"#{key}\"", exn)
|
|
802
726
|
detail = Evaluator.error_result(EvaluationReason::ERROR_EXCEPTION, default)
|
|
803
727
|
record_flag_eval_error(feature, context, default, detail.reason, with_reasons)
|
|
804
728
|
[detail, feature, exn.to_s]
|
data/lib/ldclient-rb/util.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
require "
|
|
2
|
-
require "http"
|
|
1
|
+
require "ldclient-rb/impl/util"
|
|
3
2
|
|
|
4
3
|
module LaunchDarkly
|
|
5
4
|
#
|
|
@@ -28,10 +27,11 @@ module LaunchDarkly
|
|
|
28
27
|
#
|
|
29
28
|
# @param error [String]
|
|
30
29
|
# @param exception [Exception, nil]
|
|
30
|
+
# @param headers [Hash, nil]
|
|
31
31
|
# @return [Result]
|
|
32
32
|
#
|
|
33
|
-
def self.fail(error, exception = nil)
|
|
34
|
-
Result.new(nil, error, exception)
|
|
33
|
+
def self.fail(error, exception = nil, headers = nil)
|
|
34
|
+
Result.new(nil, error, exception, headers)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
#
|
|
@@ -58,75 +58,16 @@ module LaunchDarkly
|
|
|
58
58
|
#
|
|
59
59
|
attr_reader :exception
|
|
60
60
|
|
|
61
|
-
private def initialize(value, error = nil, exception = nil)
|
|
62
|
-
@value = value
|
|
63
|
-
@error = error
|
|
64
|
-
@exception = exception
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# @private
|
|
69
|
-
module Util
|
|
70
|
-
#
|
|
71
|
-
# Append the payload filter key query parameter to the provided URI.
|
|
72
61
|
#
|
|
73
|
-
# @
|
|
74
|
-
# @param config [Config]
|
|
75
|
-
# @return [String]
|
|
62
|
+
# @return [Hash] Optional headers associated with the result
|
|
76
63
|
#
|
|
77
|
-
|
|
78
|
-
return uri if config.payload_filter_key.nil?
|
|
79
|
-
|
|
80
|
-
begin
|
|
81
|
-
parsed = URI.parse(uri)
|
|
82
|
-
new_query_params = URI.decode_www_form(String(parsed.query)) << ["filter", config.payload_filter_key]
|
|
83
|
-
parsed.query = URI.encode_www_form(new_query_params)
|
|
84
|
-
parsed.to_s
|
|
85
|
-
rescue URI::InvalidURIError
|
|
86
|
-
config.logger.warn { "[LDClient] URI could not be parsed. No filtering will be applied." }
|
|
87
|
-
uri
|
|
88
|
-
end
|
|
89
|
-
end
|
|
64
|
+
attr_reader :headers
|
|
90
65
|
|
|
91
|
-
def
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
proxy = URI.parse(uri_s).find_proxy
|
|
97
|
-
unless proxy.nil?
|
|
98
|
-
http_client_options["proxy"] = {
|
|
99
|
-
proxy_address: proxy.host,
|
|
100
|
-
proxy_port: proxy.port,
|
|
101
|
-
proxy_username: proxy.user,
|
|
102
|
-
proxy_password: proxy.password,
|
|
103
|
-
}
|
|
104
|
-
end
|
|
105
|
-
HTTP::Client.new(http_client_options)
|
|
106
|
-
.timeout({
|
|
107
|
-
read: config.read_timeout,
|
|
108
|
-
connect: config.connect_timeout,
|
|
109
|
-
})
|
|
110
|
-
.persistent(uri_s)
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def self.log_exception(logger, message, exc)
|
|
114
|
-
logger.error { "[LDClient] #{message}: #{exc.inspect}" }
|
|
115
|
-
logger.debug { "[LDClient] Exception trace: #{exc.backtrace}" }
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def self.http_error_recoverable?(status)
|
|
119
|
-
if status >= 400 && status < 500
|
|
120
|
-
status == 400 || status == 408 || status == 429
|
|
121
|
-
else
|
|
122
|
-
true
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def self.http_error_message(status, context, recoverable_message)
|
|
127
|
-
desc = (status == 401 || status == 403) ? " (invalid SDK key)" : ""
|
|
128
|
-
message = Util.http_error_recoverable?(status) ? recoverable_message : "giving up permanently"
|
|
129
|
-
"HTTP error #{status}#{desc} for #{context} - #{message}"
|
|
66
|
+
private def initialize(value, error = nil, exception = nil, headers = nil)
|
|
67
|
+
@value = value
|
|
68
|
+
@error = error
|
|
69
|
+
@exception = exception
|
|
70
|
+
@headers = headers || {}
|
|
130
71
|
end
|
|
131
72
|
end
|
|
132
73
|
end
|
data/lib/ldclient-rb/version.rb
CHANGED
data/lib/ldclient-rb.rb
CHANGED
|
@@ -5,23 +5,14 @@
|
|
|
5
5
|
module LaunchDarkly
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
require "ldclient-rb/interfaces"
|
|
10
|
-
require "ldclient-rb/util"
|
|
11
|
-
require "ldclient-rb/flags_state"
|
|
12
|
-
require "ldclient-rb/migrations"
|
|
13
|
-
require "ldclient-rb/ldclient"
|
|
14
|
-
require "ldclient-rb/cache_store"
|
|
15
|
-
require "ldclient-rb/expiring_cache"
|
|
16
|
-
require "ldclient-rb/memoized_value"
|
|
17
|
-
require "ldclient-rb/in_memory_store"
|
|
8
|
+
# Public APIs - these define the main interfaces users interact with
|
|
18
9
|
require "ldclient-rb/config"
|
|
19
10
|
require "ldclient-rb/context"
|
|
20
|
-
require "ldclient-rb/
|
|
21
|
-
require "ldclient-rb/stream"
|
|
22
|
-
require "ldclient-rb/polling"
|
|
23
|
-
require "ldclient-rb/simple_lru_cache"
|
|
24
|
-
require "ldclient-rb/non_blocking_thread_pool"
|
|
25
|
-
require "ldclient-rb/events"
|
|
26
|
-
require "ldclient-rb/requestor"
|
|
11
|
+
require "ldclient-rb/flags_state"
|
|
27
12
|
require "ldclient-rb/integrations"
|
|
13
|
+
require "ldclient-rb/interfaces"
|
|
14
|
+
require "ldclient-rb/ldclient"
|
|
15
|
+
require "ldclient-rb/migrations"
|
|
16
|
+
require "ldclient-rb/reference"
|
|
17
|
+
require "ldclient-rb/util"
|
|
18
|
+
require "ldclient-rb/version"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: launchdarkly-server-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.11.
|
|
4
|
+
version: 8.11.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- LaunchDarkly
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: aws-sdk-dynamodb
|
|
@@ -298,22 +298,22 @@ dependencies:
|
|
|
298
298
|
name: openssl
|
|
299
299
|
requirement: !ruby/object:Gem::Requirement
|
|
300
300
|
requirements:
|
|
301
|
-
- - "~>"
|
|
302
|
-
- !ruby/object:Gem::Version
|
|
303
|
-
version: '3.1'
|
|
304
301
|
- - ">="
|
|
305
302
|
- !ruby/object:Gem::Version
|
|
306
303
|
version: 3.1.2
|
|
304
|
+
- - "<"
|
|
305
|
+
- !ruby/object:Gem::Version
|
|
306
|
+
version: '5.0'
|
|
307
307
|
type: :runtime
|
|
308
308
|
prerelease: false
|
|
309
309
|
version_requirements: !ruby/object:Gem::Requirement
|
|
310
310
|
requirements:
|
|
311
|
-
- - "~>"
|
|
312
|
-
- !ruby/object:Gem::Version
|
|
313
|
-
version: '3.1'
|
|
314
311
|
- - ">="
|
|
315
312
|
- !ruby/object:Gem::Version
|
|
316
313
|
version: 3.1.2
|
|
314
|
+
- - "<"
|
|
315
|
+
- !ruby/object:Gem::Version
|
|
316
|
+
version: '5.0'
|
|
317
317
|
- !ruby/object:Gem::Dependency
|
|
318
318
|
name: semantic
|
|
319
319
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -387,23 +387,35 @@ files:
|
|
|
387
387
|
- README.md
|
|
388
388
|
- lib/launchdarkly-server-sdk.rb
|
|
389
389
|
- lib/ldclient-rb.rb
|
|
390
|
-
- lib/ldclient-rb/cache_store.rb
|
|
391
390
|
- lib/ldclient-rb/config.rb
|
|
392
391
|
- lib/ldclient-rb/context.rb
|
|
392
|
+
- lib/ldclient-rb/data_system.rb
|
|
393
393
|
- lib/ldclient-rb/evaluation_detail.rb
|
|
394
394
|
- lib/ldclient-rb/events.rb
|
|
395
|
-
- lib/ldclient-rb/expiring_cache.rb
|
|
396
395
|
- lib/ldclient-rb/flags_state.rb
|
|
397
396
|
- lib/ldclient-rb/impl.rb
|
|
398
397
|
- lib/ldclient-rb/impl/big_segments.rb
|
|
399
398
|
- lib/ldclient-rb/impl/broadcaster.rb
|
|
399
|
+
- lib/ldclient-rb/impl/cache_store.rb
|
|
400
400
|
- lib/ldclient-rb/impl/context.rb
|
|
401
401
|
- lib/ldclient-rb/impl/context_filter.rb
|
|
402
402
|
- lib/ldclient-rb/impl/data_source.rb
|
|
403
403
|
- lib/ldclient-rb/impl/data_source/null_processor.rb
|
|
404
|
+
- lib/ldclient-rb/impl/data_source/polling.rb
|
|
405
|
+
- lib/ldclient-rb/impl/data_source/requestor.rb
|
|
406
|
+
- lib/ldclient-rb/impl/data_source/status_provider.rb
|
|
407
|
+
- lib/ldclient-rb/impl/data_source/stream.rb
|
|
404
408
|
- lib/ldclient-rb/impl/data_store.rb
|
|
409
|
+
- lib/ldclient-rb/impl/data_store/data_kind.rb
|
|
410
|
+
- lib/ldclient-rb/impl/data_store/feature_store_client_wrapper.rb
|
|
411
|
+
- lib/ldclient-rb/impl/data_store/in_memory_feature_store.rb
|
|
412
|
+
- lib/ldclient-rb/impl/data_store/status_provider.rb
|
|
413
|
+
- lib/ldclient-rb/impl/data_store/store.rb
|
|
405
414
|
- lib/ldclient-rb/impl/data_system.rb
|
|
406
415
|
- lib/ldclient-rb/impl/data_system/fdv1.rb
|
|
416
|
+
- lib/ldclient-rb/impl/data_system/fdv2.rb
|
|
417
|
+
- lib/ldclient-rb/impl/data_system/polling.rb
|
|
418
|
+
- lib/ldclient-rb/impl/data_system/protocolv2.rb
|
|
407
419
|
- lib/ldclient-rb/impl/dependency_tracker.rb
|
|
408
420
|
- lib/ldclient-rb/impl/diagnostic_events.rb
|
|
409
421
|
- lib/ldclient-rb/impl/evaluation_with_hook_result.rb
|
|
@@ -414,12 +426,15 @@ files:
|
|
|
414
426
|
- lib/ldclient-rb/impl/event_sender.rb
|
|
415
427
|
- lib/ldclient-rb/impl/event_summarizer.rb
|
|
416
428
|
- lib/ldclient-rb/impl/event_types.rb
|
|
429
|
+
- lib/ldclient-rb/impl/expiring_cache.rb
|
|
417
430
|
- lib/ldclient-rb/impl/flag_tracker.rb
|
|
418
431
|
- lib/ldclient-rb/impl/integrations/consul_impl.rb
|
|
419
432
|
- lib/ldclient-rb/impl/integrations/dynamodb_impl.rb
|
|
420
433
|
- lib/ldclient-rb/impl/integrations/file_data_source.rb
|
|
421
434
|
- lib/ldclient-rb/impl/integrations/redis_impl.rb
|
|
422
435
|
- lib/ldclient-rb/impl/integrations/test_data/test_data_source.rb
|
|
436
|
+
- lib/ldclient-rb/impl/integrations/test_data/test_data_source_v2.rb
|
|
437
|
+
- lib/ldclient-rb/impl/memoized_value.rb
|
|
423
438
|
- lib/ldclient-rb/impl/migrations/migrator.rb
|
|
424
439
|
- lib/ldclient-rb/impl/migrations/tracker.rb
|
|
425
440
|
- lib/ldclient-rb/impl/model/clause.rb
|
|
@@ -427,8 +442,10 @@ files:
|
|
|
427
442
|
- lib/ldclient-rb/impl/model/preprocessed_data.rb
|
|
428
443
|
- lib/ldclient-rb/impl/model/segment.rb
|
|
429
444
|
- lib/ldclient-rb/impl/model/serialization.rb
|
|
445
|
+
- lib/ldclient-rb/impl/non_blocking_thread_pool.rb
|
|
430
446
|
- lib/ldclient-rb/impl/repeating_task.rb
|
|
431
447
|
- lib/ldclient-rb/impl/sampler.rb
|
|
448
|
+
- lib/ldclient-rb/impl/simple_lru_cache.rb
|
|
432
449
|
- lib/ldclient-rb/impl/store_client_wrapper.rb
|
|
433
450
|
- lib/ldclient-rb/impl/store_data_set_sorter.rb
|
|
434
451
|
- lib/ldclient-rb/impl/unbounded_pool.rb
|
|
@@ -441,31 +458,32 @@ files:
|
|
|
441
458
|
- lib/ldclient-rb/integrations/redis.rb
|
|
442
459
|
- lib/ldclient-rb/integrations/test_data.rb
|
|
443
460
|
- lib/ldclient-rb/integrations/test_data/flag_builder.rb
|
|
461
|
+
- lib/ldclient-rb/integrations/test_data_v2.rb
|
|
462
|
+
- lib/ldclient-rb/integrations/test_data_v2/flag_builder_v2.rb
|
|
444
463
|
- lib/ldclient-rb/integrations/util/store_wrapper.rb
|
|
445
464
|
- lib/ldclient-rb/interfaces.rb
|
|
446
465
|
- lib/ldclient-rb/interfaces/big_segment_store.rb
|
|
447
466
|
- lib/ldclient-rb/interfaces/data_source.rb
|
|
448
467
|
- lib/ldclient-rb/interfaces/data_store.rb
|
|
468
|
+
- lib/ldclient-rb/interfaces/data_system.rb
|
|
449
469
|
- lib/ldclient-rb/interfaces/feature_store.rb
|
|
450
470
|
- lib/ldclient-rb/interfaces/flag_tracker.rb
|
|
451
471
|
- lib/ldclient-rb/interfaces/hooks.rb
|
|
452
472
|
- lib/ldclient-rb/interfaces/migrations.rb
|
|
453
473
|
- lib/ldclient-rb/interfaces/plugins.rb
|
|
454
474
|
- lib/ldclient-rb/ldclient.rb
|
|
455
|
-
- lib/ldclient-rb/memoized_value.rb
|
|
456
475
|
- lib/ldclient-rb/migrations.rb
|
|
457
|
-
- lib/ldclient-rb/non_blocking_thread_pool.rb
|
|
458
|
-
- lib/ldclient-rb/polling.rb
|
|
459
476
|
- lib/ldclient-rb/reference.rb
|
|
460
|
-
- lib/ldclient-rb/requestor.rb
|
|
461
|
-
- lib/ldclient-rb/simple_lru_cache.rb
|
|
462
|
-
- lib/ldclient-rb/stream.rb
|
|
463
477
|
- lib/ldclient-rb/util.rb
|
|
464
478
|
- lib/ldclient-rb/version.rb
|
|
465
479
|
homepage: https://github.com/launchdarkly/ruby-server-sdk
|
|
466
480
|
licenses:
|
|
467
481
|
- Apache-2.0
|
|
468
|
-
metadata:
|
|
482
|
+
metadata:
|
|
483
|
+
bug_tracker_uri: https://github.com/launchdarkly/ruby-server-sdk/issues
|
|
484
|
+
changelog_uri: https://github.com/launchdarkly/ruby-server-sdk/blob/main/CHANGELOG.md
|
|
485
|
+
homepage_uri: https://github.com/launchdarkly/ruby-server-sdk
|
|
486
|
+
source_code_uri: https://github.com/launchdarkly/ruby-server-sdk
|
|
469
487
|
post_install_message:
|
|
470
488
|
rdoc_options: []
|
|
471
489
|
require_paths:
|