launchdarkly-server-sdk 8.11.1-java → 8.11.3-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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ldclient-rb/config.rb +66 -3
  3. data/lib/ldclient-rb/context.rb +1 -1
  4. data/lib/ldclient-rb/data_system.rb +243 -0
  5. data/lib/ldclient-rb/events.rb +35 -20
  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/null_processor.rb +52 -0
  10. data/lib/ldclient-rb/impl/data_source/polling.rb +108 -0
  11. data/lib/ldclient-rb/impl/data_source/requestor.rb +106 -0
  12. data/lib/ldclient-rb/impl/data_source/status_provider.rb +78 -0
  13. data/lib/ldclient-rb/impl/data_source/stream.rb +198 -0
  14. data/lib/ldclient-rb/impl/data_source.rb +3 -3
  15. data/lib/ldclient-rb/impl/data_store/data_kind.rb +108 -0
  16. data/lib/ldclient-rb/impl/data_store/feature_store_client_wrapper.rb +187 -0
  17. data/lib/ldclient-rb/impl/data_store/in_memory_feature_store.rb +130 -0
  18. data/lib/ldclient-rb/impl/data_store/status_provider.rb +82 -0
  19. data/lib/ldclient-rb/impl/data_store/store.rb +371 -0
  20. data/lib/ldclient-rb/impl/data_store.rb +11 -97
  21. data/lib/ldclient-rb/impl/data_system/fdv1.rb +178 -0
  22. data/lib/ldclient-rb/impl/data_system/fdv2.rb +471 -0
  23. data/lib/ldclient-rb/impl/data_system/polling.rb +601 -0
  24. data/lib/ldclient-rb/impl/data_system/protocolv2.rb +264 -0
  25. data/lib/ldclient-rb/impl/data_system.rb +298 -0
  26. data/lib/ldclient-rb/impl/dependency_tracker.rb +21 -9
  27. data/lib/ldclient-rb/impl/evaluator.rb +3 -2
  28. data/lib/ldclient-rb/impl/event_sender.rb +4 -3
  29. data/lib/ldclient-rb/impl/expiring_cache.rb +79 -0
  30. data/lib/ldclient-rb/impl/integrations/file_data_source.rb +9 -9
  31. data/lib/ldclient-rb/impl/integrations/test_data/test_data_source.rb +0 -1
  32. data/lib/ldclient-rb/impl/integrations/test_data/test_data_source_v2.rb +288 -0
  33. data/lib/ldclient-rb/impl/memoized_value.rb +34 -0
  34. data/lib/ldclient-rb/impl/migrations/migrator.rb +2 -1
  35. data/lib/ldclient-rb/impl/migrations/tracker.rb +2 -1
  36. data/lib/ldclient-rb/impl/model/serialization.rb +6 -6
  37. data/lib/ldclient-rb/impl/non_blocking_thread_pool.rb +48 -0
  38. data/lib/ldclient-rb/impl/repeating_task.rb +2 -2
  39. data/lib/ldclient-rb/impl/simple_lru_cache.rb +27 -0
  40. data/lib/ldclient-rb/impl/util.rb +65 -0
  41. data/lib/ldclient-rb/impl.rb +1 -2
  42. data/lib/ldclient-rb/in_memory_store.rb +1 -18
  43. data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +9 -9
  44. data/lib/ldclient-rb/integrations/test_data.rb +11 -11
  45. data/lib/ldclient-rb/integrations/test_data_v2/flag_builder_v2.rb +582 -0
  46. data/lib/ldclient-rb/integrations/test_data_v2.rb +248 -0
  47. data/lib/ldclient-rb/integrations/util/store_wrapper.rb +3 -2
  48. data/lib/ldclient-rb/interfaces/data_system.rb +755 -0
  49. data/lib/ldclient-rb/interfaces/feature_store.rb +3 -0
  50. data/lib/ldclient-rb/ldclient.rb +55 -149
  51. data/lib/ldclient-rb/util.rb +11 -70
  52. data/lib/ldclient-rb/version.rb +1 -1
  53. data/lib/ldclient-rb.rb +8 -17
  54. metadata +52 -17
  55. data/lib/ldclient-rb/cache_store.rb +0 -45
  56. data/lib/ldclient-rb/expiring_cache.rb +0 -77
  57. data/lib/ldclient-rb/memoized_value.rb +0 -32
  58. data/lib/ldclient-rb/non_blocking_thread_pool.rb +0 -46
  59. data/lib/ldclient-rb/polling.rb +0 -102
  60. data/lib/ldclient-rb/requestor.rb +0 -102
  61. data/lib/ldclient-rb/simple_lru_cache.rb +0 -25
  62. data/lib/ldclient-rb/stream.rb +0 -196
@@ -1,3 +1,6 @@
1
+ require "uri"
2
+ require "http"
3
+
1
4
  module LaunchDarkly
2
5
  module Impl
3
6
  module Util
@@ -93,6 +96,68 @@ module LaunchDarkly
93
96
  }
94
97
  nil
95
98
  end
99
+
100
+ #
101
+ # Append the payload filter key query parameter to the provided URI.
102
+ #
103
+ # @param uri [String]
104
+ # @param config [Config]
105
+ # @return [String]
106
+ #
107
+ def self.add_payload_filter_key(uri, config)
108
+ return uri if config.payload_filter_key.nil?
109
+
110
+ begin
111
+ parsed = URI.parse(uri)
112
+ new_query_params = URI.decode_www_form(String(parsed.query)) << ["filter", config.payload_filter_key]
113
+ parsed.query = URI.encode_www_form(new_query_params)
114
+ parsed.to_s
115
+ rescue URI::InvalidURIError
116
+ config.logger.warn { "[LDClient] URI could not be parsed. No filtering will be applied." }
117
+ uri
118
+ end
119
+ end
120
+
121
+ def self.new_http_client(uri_s, config)
122
+ http_client_options = {}
123
+ if config.socket_factory
124
+ http_client_options["socket_class"] = config.socket_factory
125
+ end
126
+ proxy = URI.parse(uri_s).find_proxy
127
+ unless proxy.nil?
128
+ http_client_options["proxy"] = {
129
+ proxy_address: proxy.host,
130
+ proxy_port: proxy.port,
131
+ proxy_username: proxy.user,
132
+ proxy_password: proxy.password,
133
+ }
134
+ end
135
+ HTTP::Client.new(http_client_options)
136
+ .timeout({
137
+ read: config.read_timeout,
138
+ connect: config.connect_timeout,
139
+ })
140
+ .persistent(uri_s)
141
+ end
142
+
143
+ def self.log_exception(logger, message, exc)
144
+ logger.error { "[LDClient] #{message}: #{exc.inspect}" }
145
+ logger.debug { "[LDClient] Exception trace: #{exc.backtrace}" }
146
+ end
147
+
148
+ def self.http_error_recoverable?(status)
149
+ if status >= 400 && status < 500
150
+ status == 400 || status == 408 || status == 429
151
+ else
152
+ true
153
+ end
154
+ end
155
+
156
+ def self.http_error_message(status, context, recoverable_message)
157
+ desc = (status == 401 || status == 403) ? " (invalid SDK key)" : ""
158
+ message = http_error_recoverable?(status) ? recoverable_message : "giving up permanently"
159
+ "HTTP error #{status}#{desc} for #{context} - #{message}"
160
+ end
96
161
  end
97
162
  end
98
163
  end
@@ -5,8 +5,7 @@ module LaunchDarkly
5
5
  # and subject to change.
6
6
  #
7
7
  # @since 5.5.0
8
- # @private
9
- #
8
+ # @api private
10
9
  module Impl
11
10
  # code is in ldclient-rb/impl/
12
11
  end
@@ -1,24 +1,7 @@
1
1
  require "concurrent/atomics"
2
+ require "ldclient-rb/impl/data_store"
2
3
 
3
4
  module LaunchDarkly
4
-
5
- # These constants denote the types of data that can be stored in the feature store. If
6
- # we add another storable data type in the future, as long as it follows the same pattern
7
- # (having "key", "version", and "deleted" properties), we only need to add a corresponding
8
- # constant here and the existing store should be able to handle it.
9
- #
10
- # The :priority and :get_dependency_keys properties are used by FeatureStoreDataSetSorter
11
- # to ensure data consistency during non-atomic updates.
12
-
13
- # @private
14
- FEATURES = Impl::DataStore::DataKind.new(namespace: "features", priority: 1).freeze
15
-
16
- # @private
17
- SEGMENTS = Impl::DataStore::DataKind.new(namespace: "segments", priority: 0).freeze
18
-
19
- # @private
20
- ALL_KINDS = [FEATURES, SEGMENTS].freeze
21
-
22
5
  #
23
6
  # Default implementation of the LaunchDarkly client's feature store, using an in-memory
24
7
  # cache. This object holds feature flags and related data received from LaunchDarkly.
@@ -12,14 +12,14 @@ module LaunchDarkly
12
12
  class FlagBuilder
13
13
  attr_reader :key
14
14
 
15
- # @private
15
+ # @api private
16
16
  def initialize(key)
17
17
  @key = key
18
18
  @on = true
19
19
  @variations = []
20
20
  end
21
21
 
22
- # @private
22
+ # @api private
23
23
  def initialize_copy(other)
24
24
  super(other)
25
25
  @variations = @variations.clone
@@ -357,7 +357,7 @@ module LaunchDarkly
357
357
  self
358
358
  end
359
359
 
360
- # @private
360
+ # @api private
361
361
  def add_rule(rule)
362
362
  if @rules.nil?
363
363
  @rules = Array.new
@@ -386,7 +386,7 @@ module LaunchDarkly
386
386
  end
387
387
  end
388
388
 
389
- # @private
389
+ # @api private
390
390
  def build(version)
391
391
  res = { key: @key,
392
392
  version: version,
@@ -486,16 +486,16 @@ module LaunchDarkly
486
486
  # Finally, call {#then_return} to finish defining the rule.
487
487
  #
488
488
  class FlagRuleBuilder
489
- # @private
489
+ # @api private
490
490
  FlagRuleClause = Struct.new(:contextKind, :attribute, :op, :values, :negate, keyword_init: true) # rubocop:disable Naming/MethodName:
491
491
 
492
- # @private
492
+ # @api private
493
493
  def initialize(flag_builder)
494
494
  @flag_builder = flag_builder
495
495
  @clauses = Array.new
496
496
  end
497
497
 
498
- # @private
498
+ # @api private
499
499
  def intialize_copy(other)
500
500
  super(other)
501
501
  @clauses = @clauses.clone
@@ -612,7 +612,7 @@ module LaunchDarkly
612
612
  end
613
613
  end
614
614
 
615
- # @private
615
+ # @api private
616
616
  def build(ri)
617
617
  {
618
618
  id: 'rule' + ri.to_s,
@@ -622,7 +622,7 @@ module LaunchDarkly
622
622
  end
623
623
  end
624
624
 
625
- # @private
625
+ # @api private
626
626
  def variation_for_boolean(variation)
627
627
  variation ? TRUE_VARIATION_INDEX : FALSE_VARIATION_INDEX
628
628
  end
@@ -42,7 +42,7 @@ module LaunchDarkly
42
42
  self.new
43
43
  end
44
44
 
45
- # @private
45
+ # @api private
46
46
  def initialize
47
47
  @flag_builders = Hash.new
48
48
  @current_flags = Hash.new
@@ -56,7 +56,7 @@ module LaunchDarkly
56
56
  # Called internally by the SDK to determine what arguments to pass to call
57
57
  # You do not need to call this method.
58
58
  #
59
- # @private
59
+ # @api private
60
60
  def arity
61
61
  2
62
62
  end
@@ -65,7 +65,7 @@ module LaunchDarkly
65
65
  # Called internally by the SDK to associate this test data source with an {@code LDClient} instance.
66
66
  # You do not need to call this method.
67
67
  #
68
- # @private
68
+ # @api private
69
69
  def call(_, config)
70
70
  impl = LaunchDarkly::Impl::Integrations::TestData::TestDataSource.new(config.feature_store, self)
71
71
  @instances_lock.with_write_lock { @instances.push(impl) }
@@ -121,10 +121,10 @@ module LaunchDarkly
121
121
  if @current_flags[flag_key]
122
122
  version = @current_flags[flag_key][:version]
123
123
  end
124
- new_flag = Impl::Model.deserialize(FEATURES, flag_builder.build(version+1))
124
+ new_flag = LaunchDarkly::Impl::Model.deserialize(LaunchDarkly::Impl::DataStore::FEATURES, flag_builder.build(version+1))
125
125
  @current_flags[flag_key] = new_flag
126
126
  end
127
- update_item(FEATURES, new_flag)
127
+ update_item(LaunchDarkly::Impl::DataStore::FEATURES, new_flag)
128
128
  self
129
129
  end
130
130
 
@@ -147,7 +147,7 @@ module LaunchDarkly
147
147
  # @return [TestData] the TestData instance
148
148
  #
149
149
  def use_preconfigured_flag(flag)
150
- use_preconfigured_item(FEATURES, flag, @current_flags)
150
+ use_preconfigured_item(LaunchDarkly::Impl::DataStore::FEATURES, flag, @current_flags)
151
151
  end
152
152
 
153
153
  #
@@ -167,7 +167,7 @@ module LaunchDarkly
167
167
  # @return [TestData] the TestData instance
168
168
  #
169
169
  def use_preconfigured_segment(segment)
170
- use_preconfigured_item(SEGMENTS, segment, @current_segments)
170
+ use_preconfigured_item(LaunchDarkly::Impl::DataStore::SEGMENTS, segment, @current_segments)
171
171
  end
172
172
 
173
173
  private def use_preconfigured_item(kind, item, current)
@@ -194,17 +194,17 @@ module LaunchDarkly
194
194
  end
195
195
  end
196
196
 
197
- # @private
197
+ # @api private
198
198
  def make_init_data
199
199
  @lock.with_read_lock do
200
200
  {
201
- FEATURES => @current_flags.clone,
202
- SEGMENTS => @current_segments.clone,
201
+ LaunchDarkly::Impl::DataStore::FEATURES => @current_flags.clone,
202
+ LaunchDarkly::Impl::DataStore::SEGMENTS => @current_segments.clone,
203
203
  }
204
204
  end
205
205
  end
206
206
 
207
- # @private
207
+ # @api private
208
208
  def closed_instance(instance)
209
209
  @instances_lock.with_write_lock { @instances.delete(instance) }
210
210
  end