launchdarkly-server-sdk 8.11.2-java → 8.12.0-java
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 +69 -9
- data/lib/ldclient-rb/context.rb +1 -1
- data/lib/ldclient-rb/data_system.rb +227 -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 +113 -0
- data/lib/ldclient-rb/impl/data_source/status_provider.rb +83 -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 +76 -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/data_source_builder_common.rb +77 -0
- data/lib/ldclient-rb/impl/data_system/fdv1.rb +20 -7
- data/lib/ldclient-rb/impl/data_system/fdv2.rb +472 -0
- data/lib/ldclient-rb/impl/data_system/http_config_options.rb +32 -0
- data/lib/ldclient-rb/impl/data_system/polling.rb +628 -0
- data/lib/ldclient-rb/impl/data_system/protocolv2.rb +264 -0
- data/lib/ldclient-rb/impl/data_system/streaming.rb +401 -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 +14 -6
- 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/file_data_source_v2.rb +460 -0
- data/lib/ldclient-rb/impl/integrations/test_data/test_data_source_v2.rb +290 -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/store_data_set_sorter.rb +1 -1
- data/lib/ldclient-rb/impl/util.rb +71 -0
- data/lib/ldclient-rb/impl.rb +1 -2
- data/lib/ldclient-rb/in_memory_store.rb +1 -18
- data/lib/ldclient-rb/integrations/file_data.rb +67 -0
- 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 +254 -0
- data/lib/ldclient-rb/integrations/util/store_wrapper.rb +3 -2
- data/lib/ldclient-rb/interfaces/data_system.rb +704 -0
- data/lib/ldclient-rb/interfaces/feature_store.rb +5 -2
- data/lib/ldclient-rb/ldclient.rb +66 -132
- data/lib/ldclient-rb/util.rb +11 -70
- data/lib/ldclient-rb/version.rb +1 -1
- data/lib/ldclient-rb.rb +9 -17
- metadata +41 -19
- 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
|
@@ -36,7 +36,7 @@ module LaunchDarkly
|
|
|
36
36
|
# the correct order), storing each item, and then delete any leftover items at the very end.
|
|
37
37
|
#
|
|
38
38
|
# @param all_data [Hash] a hash where each key is one of the data kind objects, and each
|
|
39
|
-
# value is in turn a hash of
|
|
39
|
+
# value is in turn a hash of symbol keys to entities
|
|
40
40
|
# @return [void]
|
|
41
41
|
#
|
|
42
42
|
def init(all_data)
|
|
@@ -46,7 +46,7 @@ module LaunchDarkly
|
|
|
46
46
|
# Returns the entity to which the specified key is mapped, if any.
|
|
47
47
|
#
|
|
48
48
|
# @param kind [Object] the kind of entity to get
|
|
49
|
-
# @param key [String] the unique key of the entity to get
|
|
49
|
+
# @param key [String, Symbol] the unique key of the entity to get
|
|
50
50
|
# @return [Hash] the entity; nil if the key was not found, or if the stored entity's
|
|
51
51
|
# `:deleted` property was true
|
|
52
52
|
#
|
|
@@ -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,17 @@
|
|
|
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"
|
|
7
|
+
require "ldclient-rb/impl/data_system/fdv2"
|
|
6
8
|
require "ldclient-rb/impl/diagnostic_events"
|
|
7
|
-
require "ldclient-rb/impl/evaluator"
|
|
8
9
|
require "ldclient-rb/impl/evaluation_with_hook_result"
|
|
10
|
+
require "ldclient-rb/impl/evaluator"
|
|
9
11
|
require "ldclient-rb/impl/flag_tracker"
|
|
10
|
-
require "ldclient-rb/impl/store_client_wrapper"
|
|
11
12
|
require "ldclient-rb/impl/migrations/tracker"
|
|
13
|
+
require "ldclient-rb/impl/util"
|
|
14
|
+
require "ldclient-rb/events"
|
|
12
15
|
require "concurrent"
|
|
13
16
|
require "concurrent/atomics"
|
|
14
17
|
require "digest/sha1"
|
|
@@ -30,6 +33,18 @@ module LaunchDarkly
|
|
|
30
33
|
|
|
31
34
|
def_delegators :@config, :logger
|
|
32
35
|
|
|
36
|
+
# @!method flush
|
|
37
|
+
# Delegates to {LaunchDarkly::EventProcessorMethods#flush}.
|
|
38
|
+
def_delegator :@event_processor, :flush
|
|
39
|
+
|
|
40
|
+
# @!method data_store_status_provider
|
|
41
|
+
# Delegates to the data system {LaunchDarkly::Impl::DataSystem#data_store_status_provider}.
|
|
42
|
+
# @return [LaunchDarkly::Interfaces::DataStore::StatusProvider]
|
|
43
|
+
# @!method data_source_status_provider
|
|
44
|
+
# Delegates to the data system {LaunchDarkly::Impl::DataSystem#data_source_status_provider}.
|
|
45
|
+
# @return [LaunchDarkly::Interfaces::DataSource::StatusProvider]
|
|
46
|
+
def_delegators :@data_system, :data_store_status_provider, :data_source_status_provider
|
|
47
|
+
|
|
33
48
|
#
|
|
34
49
|
# Creates a new client instance that connects to LaunchDarkly. A custom
|
|
35
50
|
# configuration parameter can also supplied to specify advanced options,
|
|
@@ -48,13 +63,16 @@ module LaunchDarkly
|
|
|
48
63
|
#
|
|
49
64
|
def initialize(sdk_key, config = Config.default, wait_for_sec = 5)
|
|
50
65
|
# 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
|
-
|
|
66
|
+
# fail in most configurations. However, there are some configurations where it would be OK to
|
|
67
|
+
# not provide a SDK key.
|
|
68
|
+
# * Offline mode
|
|
69
|
+
# * Using LDD mode with events disabled
|
|
70
|
+
# * Using a custom data source (like FileData) with events disabled
|
|
71
|
+
if !config.offline? && sdk_key.nil?
|
|
72
|
+
# If the data source is nil we create a default data source which requires the SDK key.
|
|
73
|
+
if config.send_events || (!config.use_ldd? && config.data_source.nil?)
|
|
74
|
+
raise ArgumentError, "sdk_key must not be nil"
|
|
75
|
+
end
|
|
58
76
|
end
|
|
59
77
|
|
|
60
78
|
@sdk_key = sdk_key
|
|
@@ -82,9 +100,10 @@ module LaunchDarkly
|
|
|
82
100
|
# @param wait_for_sec [Float] maximum time (in seconds) to wait for initialization
|
|
83
101
|
#
|
|
84
102
|
def postfork(wait_for_sec = 5)
|
|
85
|
-
@
|
|
103
|
+
@data_system = nil
|
|
86
104
|
@event_processor = nil
|
|
87
105
|
@big_segment_store_manager = nil
|
|
106
|
+
@flag_tracker = nil
|
|
88
107
|
|
|
89
108
|
start_up(wait_for_sec)
|
|
90
109
|
end
|
|
@@ -95,32 +114,29 @@ module LaunchDarkly
|
|
|
95
114
|
|
|
96
115
|
@hooks = Concurrent::Array.new(@config.hooks + plugin_hooks)
|
|
97
116
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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)
|
|
117
|
+
# Initialize the data system - use FDv2 if configured, otherwise FDv1
|
|
118
|
+
data_system_config = @config.data_system_config
|
|
119
|
+
if data_system_config.nil?
|
|
120
|
+
# Use FDv1 for backwards compatibility
|
|
121
|
+
# Note: FDv1 will update @config.feature_store to use its wrapped store
|
|
122
|
+
@data_system = Impl::DataSystem::FDv1.new(@sdk_key, @config)
|
|
123
|
+
else
|
|
124
|
+
# Use FDv2 with the provided configuration
|
|
125
|
+
@data_system = Impl::DataSystem::FDv2.new(@sdk_key, @config, data_system_config)
|
|
126
|
+
end
|
|
113
127
|
|
|
128
|
+
# Components not managed by data system
|
|
114
129
|
@big_segment_store_manager = Impl::BigSegmentStoreManager.new(@config.big_segments, @config.logger)
|
|
115
130
|
@big_segment_store_status_provider = @big_segment_store_manager.status_provider
|
|
116
131
|
|
|
117
|
-
get_flag = lambda { |key| @store.get(FEATURES, key) }
|
|
118
|
-
get_segment = lambda { |key| @store.get(SEGMENTS, key) }
|
|
132
|
+
get_flag = lambda { |key| @data_system.store.get(Impl::DataStore::FEATURES, key) }
|
|
133
|
+
get_segment = lambda { |key| @data_system.store.get(Impl::DataStore::SEGMENTS, key) }
|
|
119
134
|
get_big_segments_membership = lambda { |key| @big_segment_store_manager.get_context_membership(key) }
|
|
120
135
|
@evaluator = LaunchDarkly::Impl::Evaluator.new(get_flag, get_segment, get_big_segments_membership, @config.logger)
|
|
121
136
|
|
|
122
137
|
if !@config.offline? && @config.send_events && !@config.diagnostic_opt_out?
|
|
123
138
|
diagnostic_accumulator = Impl::DiagnosticAccumulator.new(Impl::DiagnosticAccumulator.create_diagnostic_id(@sdk_key))
|
|
139
|
+
@data_system.set_diagnostic_accumulator(diagnostic_accumulator)
|
|
124
140
|
else
|
|
125
141
|
diagnostic_accumulator = nil
|
|
126
142
|
end
|
|
@@ -131,38 +147,14 @@ module LaunchDarkly
|
|
|
131
147
|
@event_processor = EventProcessor.new(@sdk_key, @config, nil, diagnostic_accumulator)
|
|
132
148
|
end
|
|
133
149
|
|
|
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
|
|
150
|
+
# Create the flag tracker using the broadcaster from the data system
|
|
151
|
+
eval_fn = lambda { |key, context| variation(key, context, nil) }
|
|
152
|
+
@flag_tracker = Impl::FlagTracker.new(@data_system.flag_change_broadcaster, eval_fn)
|
|
162
153
|
|
|
163
154
|
register_plugins(environment_metadata)
|
|
164
155
|
|
|
165
|
-
|
|
156
|
+
# Start the data system
|
|
157
|
+
ready = @data_system.start
|
|
166
158
|
|
|
167
159
|
return unless wait_for_sec > 0
|
|
168
160
|
|
|
@@ -173,7 +165,7 @@ module LaunchDarkly
|
|
|
173
165
|
ok = ready.wait(wait_for_sec)
|
|
174
166
|
if !ok
|
|
175
167
|
@config.logger.error { "[LDClient] Timeout encountered waiting for LaunchDarkly client initialization" }
|
|
176
|
-
elsif
|
|
168
|
+
elsif !initialized?
|
|
177
169
|
@config.logger.error { "[LDClient] LaunchDarkly client initialization failed" }
|
|
178
170
|
end
|
|
179
171
|
end
|
|
@@ -236,22 +228,6 @@ module LaunchDarkly
|
|
|
236
228
|
@hooks.push(hook)
|
|
237
229
|
end
|
|
238
230
|
|
|
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
231
|
#
|
|
256
232
|
# Creates a hash string that can be used by the JavaScript SDK to identify a context.
|
|
257
233
|
# For more information, see [Secure mode](https://docs.launchdarkly.com/sdk/features/secure-mode#ruby).
|
|
@@ -288,7 +264,9 @@ module LaunchDarkly
|
|
|
288
264
|
# @return [Boolean] true if the client has been initialized
|
|
289
265
|
#
|
|
290
266
|
def initialized?
|
|
291
|
-
@config.offline? || @config.use_ldd?
|
|
267
|
+
return true if @config.offline? || @config.use_ldd?
|
|
268
|
+
|
|
269
|
+
Impl::DataSystem::DataAvailability.at_least?(@data_system.data_availability, Impl::DataSystem::DataAvailability::CACHED)
|
|
292
270
|
end
|
|
293
271
|
|
|
294
272
|
#
|
|
@@ -594,7 +572,7 @@ module LaunchDarkly
|
|
|
594
572
|
return FeatureFlagsState.new(false) if @config.offline?
|
|
595
573
|
|
|
596
574
|
unless initialized?
|
|
597
|
-
if @store.initialized?
|
|
575
|
+
if @data_system.store.initialized?
|
|
598
576
|
@config.logger.warn { "Called all_flags_state before client initialization; using last known values from data store" }
|
|
599
577
|
else
|
|
600
578
|
@config.logger.warn { "Called all_flags_state before client initialization. Data store not available; returning empty state" }
|
|
@@ -609,9 +587,9 @@ module LaunchDarkly
|
|
|
609
587
|
end
|
|
610
588
|
|
|
611
589
|
begin
|
|
612
|
-
features = @store.all(FEATURES)
|
|
590
|
+
features = @data_system.store.all(Impl::DataStore::FEATURES)
|
|
613
591
|
rescue => exn
|
|
614
|
-
Util.log_exception(@config.logger, "Unable to read flags for all_flags_state", exn)
|
|
592
|
+
Impl::Util.log_exception(@config.logger, "Unable to read flags for all_flags_state", exn)
|
|
615
593
|
return FeatureFlagsState.new(false)
|
|
616
594
|
end
|
|
617
595
|
|
|
@@ -628,7 +606,7 @@ module LaunchDarkly
|
|
|
628
606
|
detail = eval_result.detail
|
|
629
607
|
rescue => exn
|
|
630
608
|
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)
|
|
609
|
+
Impl::Util.log_exception(@config.logger, "Error evaluating flag \"#{k}\" in all_flags_state", exn)
|
|
632
610
|
end
|
|
633
611
|
|
|
634
612
|
requires_experiment_data = experiment?(f, detail.reason)
|
|
@@ -656,11 +634,9 @@ module LaunchDarkly
|
|
|
656
634
|
# @return [void]
|
|
657
635
|
def close
|
|
658
636
|
@config.logger.info { "[LDClient] Closing LaunchDarkly client..." }
|
|
659
|
-
@
|
|
637
|
+
@data_system.stop
|
|
660
638
|
@event_processor.stop
|
|
661
639
|
@big_segment_store_manager.stop
|
|
662
|
-
@store.stop
|
|
663
|
-
@shared_executor.shutdown
|
|
664
640
|
end
|
|
665
641
|
|
|
666
642
|
#
|
|
@@ -671,33 +647,6 @@ module LaunchDarkly
|
|
|
671
647
|
#
|
|
672
648
|
attr_reader :big_segment_store_status_provider
|
|
673
649
|
|
|
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
650
|
#
|
|
702
651
|
# Returns an interface for tracking changes in feature flag configurations.
|
|
703
652
|
#
|
|
@@ -705,23 +654,8 @@ module LaunchDarkly
|
|
|
705
654
|
# requesting notifications about feature flag changes using an event
|
|
706
655
|
# listener model.
|
|
707
656
|
#
|
|
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
|
|
657
|
+
def flag_tracker
|
|
658
|
+
@flag_tracker
|
|
725
659
|
end
|
|
726
660
|
|
|
727
661
|
#
|
|
@@ -731,7 +665,7 @@ module LaunchDarkly
|
|
|
731
665
|
#
|
|
732
666
|
# @return [Array<EvaluationDetail, [LaunchDarkly::Impl::Model::FeatureFlag, nil], [String, nil]>]
|
|
733
667
|
#
|
|
734
|
-
def variation_with_flag(key, context, default)
|
|
668
|
+
private def variation_with_flag(key, context, default)
|
|
735
669
|
evaluate_internal(key, context, default, false)
|
|
736
670
|
end
|
|
737
671
|
|
|
@@ -743,7 +677,7 @@ module LaunchDarkly
|
|
|
743
677
|
#
|
|
744
678
|
# @return [Array<EvaluationDetail, [LaunchDarkly::Impl::Model::FeatureFlag, nil], [String, nil]>]
|
|
745
679
|
#
|
|
746
|
-
def evaluate_internal(key, context, default, with_reasons)
|
|
680
|
+
private def evaluate_internal(key, context, default, with_reasons)
|
|
747
681
|
if @config.offline?
|
|
748
682
|
return Evaluator.error_result(EvaluationReason::ERROR_CLIENT_NOT_READY, default), nil, nil
|
|
749
683
|
end
|
|
@@ -760,8 +694,8 @@ module LaunchDarkly
|
|
|
760
694
|
return detail, nil, context.error
|
|
761
695
|
end
|
|
762
696
|
|
|
763
|
-
|
|
764
|
-
if @
|
|
697
|
+
if @data_system.data_availability != Impl::DataSystem::DataAvailability::REFRESHED
|
|
698
|
+
if @data_system.data_availability == Impl::DataSystem::DataAvailability::CACHED
|
|
765
699
|
@config.logger.warn { "[LDClient] Client has not finished initializing; using last known values from feature store" }
|
|
766
700
|
else
|
|
767
701
|
@config.logger.error { "[LDClient] Client has not finished initializing; feature store unavailable, returning default value" }
|
|
@@ -772,7 +706,7 @@ module LaunchDarkly
|
|
|
772
706
|
end
|
|
773
707
|
|
|
774
708
|
begin
|
|
775
|
-
feature = @store.get(FEATURES, key)
|
|
709
|
+
feature = @data_system.store.get(Impl::DataStore::FEATURES, key)
|
|
776
710
|
rescue
|
|
777
711
|
# Ignored
|
|
778
712
|
end
|
|
@@ -798,7 +732,7 @@ module LaunchDarkly
|
|
|
798
732
|
record_flag_eval(feature, context, detail, default, with_reasons)
|
|
799
733
|
[detail, feature, nil]
|
|
800
734
|
rescue => exn
|
|
801
|
-
Util.log_exception(@config.logger, "Error evaluating feature flag \"#{key}\"", exn)
|
|
735
|
+
Impl::Util.log_exception(@config.logger, "Error evaluating feature flag \"#{key}\"", exn)
|
|
802
736
|
detail = Evaluator.error_result(EvaluationReason::ERROR_EXCEPTION, default)
|
|
803
737
|
record_flag_eval_error(feature, context, default, detail.reason, with_reasons)
|
|
804
738
|
[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,15 @@
|
|
|
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/
|
|
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/data_system"
|
|
12
|
+
require "ldclient-rb/flags_state"
|
|
27
13
|
require "ldclient-rb/integrations"
|
|
14
|
+
require "ldclient-rb/interfaces"
|
|
15
|
+
require "ldclient-rb/ldclient"
|
|
16
|
+
require "ldclient-rb/migrations"
|
|
17
|
+
require "ldclient-rb/reference"
|
|
18
|
+
require "ldclient-rb/util"
|
|
19
|
+
require "ldclient-rb/version"
|