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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ldclient-rb/config.rb +69 -9
  3. data/lib/ldclient-rb/context.rb +1 -1
  4. data/lib/ldclient-rb/data_system.rb +227 -0
  5. data/lib/ldclient-rb/events.rb +34 -19
  6. data/lib/ldclient-rb/flags_state.rb +1 -1
  7. data/lib/ldclient-rb/impl/big_segments.rb +4 -4
  8. data/lib/ldclient-rb/impl/cache_store.rb +44 -0
  9. data/lib/ldclient-rb/impl/data_source/polling.rb +108 -0
  10. data/lib/ldclient-rb/impl/data_source/requestor.rb +113 -0
  11. data/lib/ldclient-rb/impl/data_source/status_provider.rb +83 -0
  12. data/lib/ldclient-rb/impl/data_source/stream.rb +198 -0
  13. data/lib/ldclient-rb/impl/data_source.rb +3 -3
  14. data/lib/ldclient-rb/impl/data_store/data_kind.rb +108 -0
  15. data/lib/ldclient-rb/impl/data_store/feature_store_client_wrapper.rb +187 -0
  16. data/lib/ldclient-rb/impl/data_store/in_memory_feature_store.rb +130 -0
  17. data/lib/ldclient-rb/impl/data_store/status_provider.rb +76 -0
  18. data/lib/ldclient-rb/impl/data_store/store.rb +371 -0
  19. data/lib/ldclient-rb/impl/data_store.rb +11 -97
  20. data/lib/ldclient-rb/impl/data_system/data_source_builder_common.rb +77 -0
  21. data/lib/ldclient-rb/impl/data_system/fdv1.rb +20 -7
  22. data/lib/ldclient-rb/impl/data_system/fdv2.rb +472 -0
  23. data/lib/ldclient-rb/impl/data_system/http_config_options.rb +32 -0
  24. data/lib/ldclient-rb/impl/data_system/polling.rb +628 -0
  25. data/lib/ldclient-rb/impl/data_system/protocolv2.rb +264 -0
  26. data/lib/ldclient-rb/impl/data_system/streaming.rb +401 -0
  27. data/lib/ldclient-rb/impl/dependency_tracker.rb +21 -9
  28. data/lib/ldclient-rb/impl/evaluator.rb +3 -2
  29. data/lib/ldclient-rb/impl/event_sender.rb +14 -6
  30. data/lib/ldclient-rb/impl/expiring_cache.rb +79 -0
  31. data/lib/ldclient-rb/impl/integrations/file_data_source.rb +8 -8
  32. data/lib/ldclient-rb/impl/integrations/file_data_source_v2.rb +460 -0
  33. data/lib/ldclient-rb/impl/integrations/test_data/test_data_source_v2.rb +290 -0
  34. data/lib/ldclient-rb/impl/memoized_value.rb +34 -0
  35. data/lib/ldclient-rb/impl/migrations/migrator.rb +2 -1
  36. data/lib/ldclient-rb/impl/migrations/tracker.rb +2 -1
  37. data/lib/ldclient-rb/impl/model/serialization.rb +6 -6
  38. data/lib/ldclient-rb/impl/non_blocking_thread_pool.rb +48 -0
  39. data/lib/ldclient-rb/impl/repeating_task.rb +2 -2
  40. data/lib/ldclient-rb/impl/simple_lru_cache.rb +27 -0
  41. data/lib/ldclient-rb/impl/store_data_set_sorter.rb +1 -1
  42. data/lib/ldclient-rb/impl/util.rb +71 -0
  43. data/lib/ldclient-rb/impl.rb +1 -2
  44. data/lib/ldclient-rb/in_memory_store.rb +1 -18
  45. data/lib/ldclient-rb/integrations/file_data.rb +67 -0
  46. data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +9 -9
  47. data/lib/ldclient-rb/integrations/test_data.rb +11 -11
  48. data/lib/ldclient-rb/integrations/test_data_v2/flag_builder_v2.rb +582 -0
  49. data/lib/ldclient-rb/integrations/test_data_v2.rb +254 -0
  50. data/lib/ldclient-rb/integrations/util/store_wrapper.rb +3 -2
  51. data/lib/ldclient-rb/interfaces/data_system.rb +704 -0
  52. data/lib/ldclient-rb/interfaces/feature_store.rb +5 -2
  53. data/lib/ldclient-rb/ldclient.rb +66 -132
  54. data/lib/ldclient-rb/util.rb +11 -70
  55. data/lib/ldclient-rb/version.rb +1 -1
  56. data/lib/ldclient-rb.rb +9 -17
  57. metadata +41 -19
  58. data/lib/ldclient-rb/cache_store.rb +0 -45
  59. data/lib/ldclient-rb/expiring_cache.rb +0 -77
  60. data/lib/ldclient-rb/memoized_value.rb +0 -32
  61. data/lib/ldclient-rb/non_blocking_thread_pool.rb +0 -46
  62. data/lib/ldclient-rb/polling.rb +0 -102
  63. data/lib/ldclient-rb/requestor.rb +0 -102
  64. data/lib/ldclient-rb/simple_lru_cache.rb +0 -25
  65. 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 string keys to entities
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
@@ -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/data_source/null_processor"
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
- # (offline = true, *or* we are using LDD mode or the file data source and events are disabled
53
- # so we're not connecting to any LD services) so rather than try to check for all of those
54
- # up front, we will let the constructors for the data source implementations implement this
55
- # fail-fast as appropriate, and just check here for the part regarding events.
56
- if !config.offline? && config.send_events
57
- raise ArgumentError, "sdk_key must not be nil" if sdk_key.nil?
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
- @data_source = nil
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
- @shared_executor = Concurrent::SingleThreadExecutor.new
99
-
100
- data_store_broadcaster = LaunchDarkly::Impl::Broadcaster.new(@shared_executor, @config.logger)
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)
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
- if @config.use_ldd?
135
- @config.logger.info { "[LDClient] Started LaunchDarkly Client in LDD mode" }
136
- @data_source = LaunchDarkly::Impl::DataSource::NullUpdateProcessor.new
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
- ready = @data_source.start
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 !@data_source.initialized?
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? || @data_source.initialized?
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
- @data_source.stop
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
- attr_reader :flag_tracker
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
- unless initialized?
764
- if @store.initialized?
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]
@@ -1,5 +1,4 @@
1
- require "uri"
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
- # @param uri [String]
74
- # @param config [Config]
75
- # @return [String]
62
+ # @return [Hash] Optional headers associated with the result
76
63
  #
77
- def self.add_payload_filter_key(uri, config)
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 self.new_http_client(uri_s, config)
92
- http_client_options = {}
93
- if config.socket_factory
94
- http_client_options["socket_class"] = config.socket_factory
95
- end
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
@@ -1,3 +1,3 @@
1
1
  module LaunchDarkly
2
- VERSION = "8.11.2" # x-release-please-version
2
+ VERSION = "8.12.0" # x-release-please-version
3
3
  end
data/lib/ldclient-rb.rb CHANGED
@@ -5,23 +5,15 @@
5
5
  module LaunchDarkly
6
6
  end
7
7
 
8
- require "ldclient-rb/version"
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/reference"
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/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"