launchdarkly-server-sdk 6.3.1 → 6.3.2

Sign up to get free protection for your applications and to get access to all the features.
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