launchdarkly-server-sdk 6.3.1 → 6.3.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d21f900f036d19f8b33271d825f3c00cda01d0ac44caf875774a196950ce2479
4
- data.tar.gz: f409fa9e445a0387ef96256d6a8cc57320ebe354cc07cc9f1f78897eff5fc82f
3
+ metadata.gz: 70c2bfa2af852ab863bdd25cceedb4ac6eca57bfb4d6ccd9df70653b73a862e0
4
+ data.tar.gz: 38d1bef24f2ce6cced2342264e0b70dde44ee79dcdfb4199ff90b9b4319303eb
5
5
  SHA512:
6
- metadata.gz: 21b358fa934cbe2d5c06e9f941ebbfeb785a3d93b2bbe562859fc59af3137b0b5673de8794d1d4a32c33f2e12d212c27451242ef85c9341ac2c0c59b80d5c5d5
7
- data.tar.gz: fef2084a06846e16047d96a784b1d00351d45489baa657a48970a28190ebab67fdcc39a1716138c5b2c7f6d210be97d8289863d6f04c6a36a8bec2b5a8d49389
6
+ metadata.gz: f44affa6d4f7beb1c21be04f91caa39acd708a44fc642768c5c42419e8a2295f59592531c1e07f5ed8e407bbb1a97817b42c6be1e54ef2a80e20b1e014b57836
7
+ data.tar.gz: fe229a2d10add2afbc5fe539ca494fe8e73ae9b586571436e9bae9a3275721735ac755b35b40b6e432b69fec91803191bfe2c3bff1b876f30f3ef9de950af3eb
data/README.md CHANGED
@@ -4,7 +4,6 @@ LaunchDarkly Server-side SDK for Ruby
4
4
  [![Gem Version](https://badge.fury.io/rb/launchdarkly-server-sdk.svg)](http://badge.fury.io/rb/launchdarkly-server-sdk)
5
5
 
6
6
  [![Circle CI](https://circleci.com/gh/launchdarkly/ruby-server-sdk/tree/master.svg?style=svg)](https://circleci.com/gh/launchdarkly/ruby-server-sdk/tree/master)
7
- [![Security](https://hakiri.io/github/launchdarkly/ruby-server-sdk/master.svg)](https://hakiri.io/github/launchdarkly/ruby-server-sdk/master)
8
7
  [![RubyDoc](https://img.shields.io/static/v1?label=docs+-+all+versions&message=reference&color=00add8)](https://www.rubydoc.info/gems/launchdarkly-server-sdk)
9
8
  [![GitHub Pages](https://img.shields.io/static/v1?label=docs+-+latest&message=reference&color=00add8)](https://launchdarkly.github.io/ruby-server-sdk)
10
9
 
@@ -21,6 +21,7 @@ module LaunchDarkly
21
21
  # @option opts [Integer] :capacity (10000) See {#capacity}.
22
22
  # @option opts [Float] :flush_interval (30) See {#flush_interval}.
23
23
  # @option opts [Float] :read_timeout (10) See {#read_timeout}.
24
+ # @option opts [Float] :initial_reconnect_delay (1) See {#initial_reconnect_delay}.
24
25
  # @option opts [Float] :connect_timeout (2) See {#connect_timeout}.
25
26
  # @option opts [Object] :cache_store See {#cache_store}.
26
27
  # @option opts [Object] :feature_store See {#feature_store}.
@@ -54,6 +55,7 @@ module LaunchDarkly
54
55
  @flush_interval = opts[:flush_interval] || Config.default_flush_interval
55
56
  @connect_timeout = opts[:connect_timeout] || Config.default_connect_timeout
56
57
  @read_timeout = opts[:read_timeout] || Config.default_read_timeout
58
+ @initial_reconnect_delay = opts[:initial_reconnect_delay] || Config.default_initial_reconnect_delay
57
59
  @feature_store = opts[:feature_store] || Config.default_feature_store
58
60
  @stream = opts.has_key?(:stream) ? opts[:stream] : Config.default_stream
59
61
  @use_ldd = opts.has_key?(:use_ldd) ? opts[:use_ldd] : Config.default_use_ldd
@@ -180,6 +182,13 @@ module LaunchDarkly
180
182
  #
181
183
  attr_reader :read_timeout
182
184
 
185
+ #
186
+ # The initial delay before reconnecting after an error in the SSE client.
187
+ # This only applies to the streaming connection.
188
+ # @return [Float]
189
+ #
190
+ attr_reader :initial_reconnect_delay
191
+
183
192
  #
184
193
  # The connect timeout for network connections in seconds.
185
194
  # @return [Float]
@@ -395,6 +404,14 @@ module LaunchDarkly
395
404
  10
396
405
  end
397
406
 
407
+ #
408
+ # The default value for {#initial_reconnect_delay}.
409
+ # @return [Float] 1
410
+ #
411
+ def self.default_initial_reconnect_delay
412
+ 1
413
+ end
414
+
398
415
  #
399
416
  # The default value for {#connect_timeout}.
400
417
  # @return [Float] 10
@@ -16,21 +16,32 @@ module LaunchDarkly
16
16
 
17
17
  # Used internally to build the state map.
18
18
  # @private
19
- def add_flag(flag, value, variation, reason = nil, details_only_if_tracked = false)
20
- key = flag[:key]
21
- @flag_values[key] = value
19
+ def add_flag(flag_state, with_reasons, details_only_if_tracked)
20
+ key = flag_state[:key]
21
+ @flag_values[key] = flag_state[:value]
22
22
  meta = {}
23
- with_details = !details_only_if_tracked || flag[:trackEvents]
24
- if !with_details && flag[:debugEventsUntilDate]
25
- with_details = flag[:debugEventsUntilDate] > Impl::Util::current_time_millis
23
+
24
+ omit_details = false
25
+ if details_only_if_tracked
26
+ if !flag_state[:trackEvents] && !flag_state[:trackReason] && !(flag_state[:debugEventsUntilDate] && flag_state[:debugEventsUntilDate] > Impl::Util::current_time_millis)
27
+ omit_details = true
28
+ end
29
+ end
30
+
31
+ reason = (!with_reasons and !flag_state[:trackReason]) ? nil : flag_state[:reason]
32
+
33
+ if !reason.nil? && !omit_details
34
+ meta[:reason] = reason
26
35
  end
27
- if with_details
28
- meta[:version] = flag[:version]
29
- meta[:reason] = reason if !reason.nil?
36
+
37
+ if !omit_details
38
+ meta[:version] = flag_state[:version]
30
39
  end
31
- meta[:variation] = variation if !variation.nil?
32
- meta[:trackEvents] = true if flag[:trackEvents]
33
- meta[:debugEventsUntilDate] = flag[:debugEventsUntilDate] if flag[:debugEventsUntilDate]
40
+
41
+ meta[:variation] = flag_state[:variation] if !flag_state[:variation].nil?
42
+ meta[:trackEvents] = true if flag_state[:trackEvents]
43
+ meta[:trackReason] = true if flag_state[:trackReason]
44
+ meta[:debugEventsUntilDate] = flag_state[:debugEventsUntilDate] if flag_state[:debugEventsUntilDate]
34
45
  @flag_metadata[key] = meta
35
46
  end
36
47
 
@@ -89,7 +89,7 @@ module LaunchDarkly
89
89
 
90
90
  private
91
91
 
92
- BUILTINS = Set[:key, :ip, :country, :email, :firstName, :lastName, :avatar, :name, :anonymous]
92
+ BUILTINS = Set[:key, :secondary, :ip, :country, :email, :firstName, :lastName, :avatar, :name, :anonymous]
93
93
  NUMERIC_VERSION_COMPONENTS_REGEX = Regexp.new("^[0-9.]*")
94
94
 
95
95
  private_constant :BUILTINS
@@ -13,7 +13,7 @@ module LaunchDarkly
13
13
  end
14
14
 
15
15
  def new_eval_event(flag, user, detail, default_value, prereq_of_flag = nil)
16
- add_experiment_data = is_experiment(flag, detail.reason)
16
+ add_experiment_data = self.class.is_experiment(flag, detail.reason)
17
17
  e = {
18
18
  kind: 'feature',
19
19
  key: flag[:key],
@@ -91,17 +91,7 @@ module LaunchDarkly
91
91
  e
92
92
  end
93
93
 
94
- private
95
-
96
- def context_to_context_kind(user)
97
- if !user.nil? && user[:anonymous]
98
- return "anonymousUser"
99
- else
100
- return "user"
101
- end
102
- end
103
-
104
- def is_experiment(flag, reason)
94
+ def self.is_experiment(flag, reason)
105
95
  return false if !reason
106
96
 
107
97
  if reason.in_experiment
@@ -121,6 +111,13 @@ module LaunchDarkly
121
111
  false
122
112
  end
123
113
 
114
+ private def context_to_context_kind(user)
115
+ if !user.nil? && user[:anonymous]
116
+ return "anonymousUser"
117
+ else
118
+ return "user"
119
+ end
120
+ end
124
121
  end
125
122
  end
126
123
  end
@@ -35,7 +35,7 @@ module LaunchDarkly
35
35
  @client = Aws::DynamoDB::Client.new(opts[:dynamodb_opts] || {})
36
36
  end
37
37
 
38
- @logger.info("${description}: using DynamoDB table \"#{table_name}\"")
38
+ @logger.info("#{description}: using DynamoDB table \"#{table_name}\"")
39
39
  end
40
40
 
41
41
  def stop
@@ -36,7 +36,7 @@ module LaunchDarkly
36
36
  # @option opts [Integer] :capacity (1000) maximum number of items in the cache
37
37
  # @return [LaunchDarkly::Interfaces::FeatureStore] a feature store object
38
38
  #
39
- def self.new_feature_store(opts, &block)
39
+ def self.new_feature_store(opts = {})
40
40
  core = LaunchDarkly::Impl::Integrations::Consul::ConsulFeatureStoreCore.new(opts)
41
41
  return LaunchDarkly::Integrations::Util::CachingStoreWrapper.new(core, opts)
42
42
  end
@@ -46,7 +46,7 @@ module LaunchDarkly
46
46
  # @option opts [Integer] :capacity (1000) maximum number of items in the cache
47
47
  # @return [LaunchDarkly::Interfaces::FeatureStore] a feature store object
48
48
  #
49
- def self.new_feature_store(table_name, opts)
49
+ def self.new_feature_store(table_name, opts = {})
50
50
  core = LaunchDarkly::Impl::Integrations::DynamoDB::DynamoDBFeatureStoreCore.new(table_name, opts)
51
51
  LaunchDarkly::Integrations::Util::CachingStoreWrapper.new(core, opts)
52
52
  end
@@ -58,7 +58,7 @@ module LaunchDarkly
58
58
  # lifecycle to be independent of the SDK client
59
59
  # @return [LaunchDarkly::Interfaces::FeatureStore] a feature store object
60
60
  #
61
- def self.new_feature_store(opts)
61
+ def self.new_feature_store(opts = {})
62
62
  return RedisFeatureStore.new(opts)
63
63
  end
64
64
 
@@ -65,7 +65,7 @@ module LaunchDarkly
65
65
  get_segment = lambda { |key| @store.get(SEGMENTS, key) }
66
66
  get_big_segments_membership = lambda { |key| @big_segment_store_manager.get_user_membership(key) }
67
67
  @evaluator = LaunchDarkly::Impl::Evaluator.new(get_flag, get_segment, get_big_segments_membership, @config.logger)
68
-
68
+
69
69
  if !@config.offline? && @config.send_events && !@config.diagnostic_opt_out?
70
70
  diagnostic_accumulator = Impl::DiagnosticAccumulator.new(Impl::DiagnosticAccumulator.create_diagnostic_id(sdk_key))
71
71
  else
@@ -178,7 +178,7 @@ module LaunchDarkly
178
178
  # Other supported user attributes include IP address, country code, and an arbitrary hash of
179
179
  # custom attributes. For more about the supported user properties and how they work in
180
180
  # LaunchDarkly, see [Targeting users](https://docs.launchdarkly.com/home/flags/targeting-users).
181
- #
181
+ #
182
182
  # The optional `:privateAttributeNames` user property allows you to specify a list of
183
183
  # attribute names that should not be sent back to LaunchDarkly.
184
184
  # [Private attributes](https://docs.launchdarkly.com/home/users/attributes#creating-private-user-attributes)
@@ -248,8 +248,8 @@ module LaunchDarkly
248
248
  # @return [void]
249
249
  #
250
250
  def identify(user)
251
- if !user || user[:key].nil?
252
- @config.logger.warn("Identify called with nil user or nil user key!")
251
+ if !user || user[:key].nil? || user[:key].empty?
252
+ @config.logger.warn("Identify called with nil user or empty user key!")
253
253
  return
254
254
  end
255
255
  sanitize_user(user)
@@ -338,6 +338,15 @@ module LaunchDarkly
338
338
  def all_flags_state(user, options={})
339
339
  return FeatureFlagsState.new(false) if @config.offline?
340
340
 
341
+ if !initialized?
342
+ if @store.initialized?
343
+ @config.logger.warn { "Called all_flags_state before client initialization; using last known values from data store" }
344
+ else
345
+ @config.logger.warn { "Called all_flags_state before client initialization. Data store not available; returning empty state" }
346
+ return FeatureFlagsState.new(false)
347
+ end
348
+ end
349
+
341
350
  unless user && !user[:key].nil?
342
351
  @config.logger.error { "[LDClient] User and user key must be specified in all_flags_state" }
343
352
  return FeatureFlagsState.new(false)
@@ -359,14 +368,25 @@ module LaunchDarkly
359
368
  next
360
369
  end
361
370
  begin
362
- result = @evaluator.evaluate(f, user, @event_factory_default)
363
- state.add_flag(f, result.detail.value, result.detail.variation_index, with_reasons ? result.detail.reason : nil,
364
- details_only_if_tracked)
371
+ detail = @evaluator.evaluate(f, user, @event_factory_default).detail
365
372
  rescue => exn
373
+ detail = EvaluationDetail.new(nil, nil, EvaluationReason::error(EvaluationReason::ERROR_EXCEPTION))
366
374
  Util.log_exception(@config.logger, "Error evaluating flag \"#{k}\" in all_flags_state", exn)
367
- state.add_flag(f, nil, nil, with_reasons ? EvaluationReason::error(EvaluationReason::ERROR_EXCEPTION) : nil,
368
- details_only_if_tracked)
369
375
  end
376
+
377
+ requires_experiment_data = EventFactory.is_experiment(f, detail.reason)
378
+ flag_state = {
379
+ key: f[:key],
380
+ value: detail.value,
381
+ variation: detail.variation_index,
382
+ reason: detail.reason,
383
+ version: f[:version],
384
+ trackEvents: f[:trackEvents] || requires_experiment_data,
385
+ trackReason: requires_experiment_data,
386
+ debugEventsUntilDate: f[:debugEventsUntilDate],
387
+ }
388
+
389
+ state.add_flag(flag_state, with_reasons, details_only_if_tracked)
370
390
  end
371
391
 
372
392
  state
@@ -47,7 +47,8 @@ module LaunchDarkly
47
47
  headers: headers,
48
48
  read_timeout: READ_TIMEOUT_SECONDS,
49
49
  logger: @config.logger,
50
- socket_factory: @config.socket_factory
50
+ socket_factory: @config.socket_factory,
51
+ reconnect_time: @config.initial_reconnect_delay
51
52
  }
52
53
  log_connection_started
53
54
  @es = SSE::Client.new(@config.stream_uri + "/all", **opts) do |conn|
@@ -24,6 +24,15 @@ module LaunchDarkly
24
24
  if config.socket_factory
25
25
  http_client_options["socket_class"] = config.socket_factory
26
26
  end
27
+ proxy = URI.parse(uri_s).find_proxy
28
+ if !proxy.nil?
29
+ http_client_options["proxy"] = {
30
+ proxy_address: proxy.host,
31
+ proxy_port: proxy.port,
32
+ proxy_username: proxy.user,
33
+ proxy_password: proxy.password
34
+ }
35
+ end
27
36
  return HTTP::Client.new(http_client_options)
28
37
  .timeout({
29
38
  read: config.read_timeout,
@@ -1,3 +1,3 @@
1
1
  module LaunchDarkly
2
- VERSION = "6.3.1"
2
+ VERSION = "6.3.2"
3
3
  end
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: 6.3.1
4
+ version: 6.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - LaunchDarkly
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-31 00:00:00.000000000 Z
11
+ date: 2022-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-dynamodb
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 2.2.10
33
+ version: 2.2.33
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 2.2.10
40
+ version: 2.2.33
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -319,7 +319,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
319
319
  - !ruby/object:Gem::Version
320
320
  version: '0'
321
321
  requirements: []
322
- rubygems_version: 3.3.4
322
+ rubygems_version: 3.3.9
323
323
  signing_key:
324
324
  specification_version: 4
325
325
  summary: LaunchDarkly SDK for Ruby