launchdarkly-server-sdk 8.4.2 → 8.6.0
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 +11 -0
- data/lib/ldclient-rb/context.rb +63 -0
- data/lib/ldclient-rb/events.rb +18 -5
- data/lib/ldclient-rb/impl/integrations/file_data_source.rb +15 -11
- data/lib/ldclient-rb/integrations/file_data.rb +1 -1
- data/lib/ldclient-rb/ldclient.rb +12 -7
- data/lib/ldclient-rb/reference.rb +10 -0
- data/lib/ldclient-rb/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a732ff00a5e21bfc907dff44adc5bd3f1651bd80c2483273a1a9730f443448f
|
4
|
+
data.tar.gz: 1ca26bf847c2387ed585e07b18c6aa42a78496110a7bf9643751a0e2b04d2908
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 901e6f7562f0861916bf06fd07088561713579633cc5e052ae5cf86c6acdbdd0497b55e273c2f92244a5653d0fa806c9776f92a853bad22232634489c630f85d
|
7
|
+
data.tar.gz: a325418b21c256a8b2d846d187e8bc91ba1e323955f460a418732b77f30354b64fc2dbfdadd04c4be4a41217779a4f217d522799ace4ce46a3ebc5019baf060c
|
data/lib/ldclient-rb/config.rb
CHANGED
@@ -43,6 +43,7 @@ module LaunchDarkly
|
|
43
43
|
# @option opts [BigSegmentsConfig] :big_segments See {#big_segments}.
|
44
44
|
# @option opts [Hash] :application See {#application}
|
45
45
|
# @option opts [String] :payload_filter_key See {#payload_filter_key}
|
46
|
+
# @option opts [Boolean] :omit_anonymous_contexts See {#omit_anonymous_contexts}
|
46
47
|
# @option hooks [Array<Interfaces::Hooks::Hook]
|
47
48
|
#
|
48
49
|
def initialize(opts = {})
|
@@ -77,6 +78,7 @@ module LaunchDarkly
|
|
77
78
|
@application = LaunchDarkly::Impl::Util.validate_application_info(opts[:application] || {}, @logger)
|
78
79
|
@payload_filter_key = opts[:payload_filter_key]
|
79
80
|
@hooks = (opts[:hooks] || []).keep_if { |hook| hook.is_a? Interfaces::Hooks::Hook }
|
81
|
+
@omit_anonymous_contexts = opts.has_key?(:omit_anonymous_contexts) && opts[:omit_anonymous_contexts]
|
80
82
|
@data_source_update_sink = nil
|
81
83
|
end
|
82
84
|
|
@@ -385,6 +387,15 @@ module LaunchDarkly
|
|
385
387
|
#
|
386
388
|
attr_reader :hooks
|
387
389
|
|
390
|
+
#
|
391
|
+
# Sets whether anonymous contexts should be omitted from index and identify events.
|
392
|
+
#
|
393
|
+
# The default value is false. Anonymous contexts will be included in index and identify events.
|
394
|
+
# @return [Boolean]
|
395
|
+
#
|
396
|
+
attr_reader :omit_anonymous_contexts
|
397
|
+
|
398
|
+
|
388
399
|
#
|
389
400
|
# The default LaunchDarkly client configuration. This configuration sets
|
390
401
|
# reasonable defaults for most users.
|
data/lib/ldclient-rb/context.rb
CHANGED
@@ -101,6 +101,26 @@ module LaunchDarkly
|
|
101
101
|
@error.nil?
|
102
102
|
end
|
103
103
|
|
104
|
+
#
|
105
|
+
# For a multi-kind context:
|
106
|
+
#
|
107
|
+
# A multi-kind context is made up of two or more single-kind contexts. This method will first discard any
|
108
|
+
# single-kind contexts which are anonymous. It will then create a new multi-kind context from the remaining
|
109
|
+
# single-kind contexts. This may result in an invalid context (e.g. all single-kind contexts are anonymous).
|
110
|
+
#
|
111
|
+
# For a single-kind context:
|
112
|
+
#
|
113
|
+
# If the context is not anonymous, this method will return the current context as is and unmodified.
|
114
|
+
#
|
115
|
+
# If the context is anonymous, this method will return an invalid context.
|
116
|
+
#
|
117
|
+
def without_anonymous_contexts
|
118
|
+
contexts = multi_kind? ? @contexts : [self]
|
119
|
+
contexts = contexts.reject { |c| c.anonymous }
|
120
|
+
|
121
|
+
LDContext.create_multi(contexts)
|
122
|
+
end
|
123
|
+
|
104
124
|
#
|
105
125
|
# Returns a hash mapping each context's kind to its key.
|
106
126
|
#
|
@@ -334,6 +354,49 @@ module LaunchDarkly
|
|
334
354
|
multi_kind? ? individual_context(key.to_s) : get_value(key)
|
335
355
|
end
|
336
356
|
|
357
|
+
#
|
358
|
+
# Convert the LDContext to a JSON string.
|
359
|
+
#
|
360
|
+
# @param args [Array]
|
361
|
+
# @return [String]
|
362
|
+
#
|
363
|
+
def to_json(*args)
|
364
|
+
JSON.generate(to_h, *args)
|
365
|
+
end
|
366
|
+
|
367
|
+
#
|
368
|
+
# Convert the LDContext to a hash. If the LDContext is invalid, the hash will contain an error key with the error
|
369
|
+
# message.
|
370
|
+
#
|
371
|
+
# @return [Hash]
|
372
|
+
#
|
373
|
+
def to_h
|
374
|
+
return {error: error} unless valid?
|
375
|
+
return hash_single_kind unless multi_kind?
|
376
|
+
|
377
|
+
hash = {kind: 'multi'}
|
378
|
+
@contexts.each do |context|
|
379
|
+
single_kind_hash = context.to_h
|
380
|
+
kind = single_kind_hash.delete(:kind)
|
381
|
+
hash[kind] = single_kind_hash
|
382
|
+
end
|
383
|
+
|
384
|
+
hash
|
385
|
+
end
|
386
|
+
|
387
|
+
protected def hash_single_kind
|
388
|
+
hash = attributes.nil? ? {} : attributes.clone
|
389
|
+
|
390
|
+
hash[:kind] = kind
|
391
|
+
hash[:key] = key
|
392
|
+
|
393
|
+
hash[:name] = name unless name.nil?
|
394
|
+
hash[:anonymous] = anonymous if anonymous
|
395
|
+
hash[:_meta] = {privateAttributes: private_attributes} unless private_attributes.empty?
|
396
|
+
|
397
|
+
hash
|
398
|
+
end
|
399
|
+
|
337
400
|
#
|
338
401
|
# Retrieve the value of any top level, addressable attribute.
|
339
402
|
#
|
data/lib/ldclient-rb/events.rb
CHANGED
@@ -144,6 +144,7 @@ module LaunchDarkly
|
|
144
144
|
Impl::EventSender.new(sdk_key, config, client || Util.new_http_client(config.events_uri, config))
|
145
145
|
|
146
146
|
@timestamp_fn = (test_properties || {})[:timestamp_fn] || proc { Impl::Util.current_time_millis }
|
147
|
+
@omit_anonymous_contexts = config.omit_anonymous_contexts
|
147
148
|
|
148
149
|
EventDispatcher.new(@inbox, sdk_key, config, diagnostic_accumulator, event_sender)
|
149
150
|
end
|
@@ -167,7 +168,8 @@ module LaunchDarkly
|
|
167
168
|
end
|
168
169
|
|
169
170
|
def record_identify_event(context)
|
170
|
-
|
171
|
+
target_context = !@omit_anonymous_contexts ? context : context.without_anonymous_contexts
|
172
|
+
post_to_inbox(LaunchDarkly::Impl::IdentifyEvent.new(timestamp, target_context)) if target_context.valid?
|
171
173
|
end
|
172
174
|
|
173
175
|
def record_custom_event(context, key, data = nil, metric_value = nil)
|
@@ -319,16 +321,27 @@ module LaunchDarkly
|
|
319
321
|
will_add_full_event = true
|
320
322
|
end
|
321
323
|
|
322
|
-
|
323
|
-
|
324
|
-
if !event.context.nil? && !notice_context(event.context) && !event.is_a?(LaunchDarkly::Impl::IdentifyEvent) && !event.is_a?(LaunchDarkly::Impl::MigrationOpEvent)
|
325
|
-
outbox.add_event(LaunchDarkly::Impl::IndexEvent.new(event.timestamp, event.context))
|
324
|
+
get_indexable_context(event) do |ctx|
|
325
|
+
outbox.add_event(LaunchDarkly::Impl::IndexEvent.new(event.timestamp, ctx))
|
326
326
|
end
|
327
327
|
|
328
328
|
outbox.add_event(event) if will_add_full_event && @sampler.sample(event.sampling_ratio.nil? ? 1 : event.sampling_ratio)
|
329
329
|
outbox.add_event(debug_event) if !debug_event.nil? && @sampler.sample(event.sampling_ratio.nil? ? 1 : event.sampling_ratio)
|
330
330
|
end
|
331
331
|
|
332
|
+
private def get_indexable_context(event, &block)
|
333
|
+
return if event.context.nil?
|
334
|
+
|
335
|
+
context = !@config.omit_anonymous_contexts ? event.context : event.context.without_anonymous_contexts
|
336
|
+
return unless context.valid?
|
337
|
+
|
338
|
+
return if notice_context(context)
|
339
|
+
return if event.is_a?(LaunchDarkly::Impl::IdentifyEvent)
|
340
|
+
return if event.is_a?(LaunchDarkly::Impl::MigrationOpEvent)
|
341
|
+
|
342
|
+
yield context unless block.nil?
|
343
|
+
end
|
344
|
+
|
332
345
|
#
|
333
346
|
# Add to the set of contexts we've noticed, and return true if the context
|
334
347
|
# was already known to us.
|
@@ -36,18 +36,13 @@ module LaunchDarkly
|
|
36
36
|
@paths = [ @paths ]
|
37
37
|
end
|
38
38
|
@auto_update = options[:auto_update]
|
39
|
-
|
40
|
-
# We have seen unreliable behavior in the 'listen' gem in JRuby 9.1 (https://github.com/guard/listen/issues/449).
|
41
|
-
# Therefore, on that platform we'll fall back to file polling instead.
|
42
|
-
if defined?(JRUBY_VERSION) && JRUBY_VERSION.start_with?("9.1.")
|
43
|
-
@use_listen = false
|
44
|
-
else
|
45
|
-
@use_listen = true
|
46
|
-
end
|
47
|
-
end
|
39
|
+
@use_listen = @auto_update && @@have_listen && !options[:force_polling]
|
48
40
|
@poll_interval = options[:poll_interval] || 1
|
49
41
|
@initialized = Concurrent::AtomicBoolean.new(false)
|
50
42
|
@ready = Concurrent::Event.new
|
43
|
+
|
44
|
+
@version_lock = Mutex.new
|
45
|
+
@last_version = 1
|
51
46
|
end
|
52
47
|
|
53
48
|
def initialized?
|
@@ -101,14 +96,22 @@ module LaunchDarkly
|
|
101
96
|
end
|
102
97
|
|
103
98
|
def load_file(path, all_data)
|
99
|
+
version = 1
|
100
|
+
@version_lock.synchronize {
|
101
|
+
version = @last_version
|
102
|
+
@last_version += 1
|
103
|
+
}
|
104
|
+
|
104
105
|
parsed = parse_content(IO.read(path))
|
105
106
|
(parsed[:flags] || {}).each do |key, flag|
|
107
|
+
flag[:version] = version
|
106
108
|
add_item(all_data, FEATURES, flag)
|
107
109
|
end
|
108
110
|
(parsed[:flagValues] || {}).each do |key, value|
|
109
|
-
add_item(all_data, FEATURES, make_flag_with_value(key.to_s, value))
|
111
|
+
add_item(all_data, FEATURES, make_flag_with_value(key.to_s, value, version))
|
110
112
|
end
|
111
113
|
(parsed[:segments] || {}).each do |key, segment|
|
114
|
+
segment[:version] = version
|
112
115
|
add_item(all_data, SEGMENTS, segment)
|
113
116
|
end
|
114
117
|
end
|
@@ -142,10 +145,11 @@ module LaunchDarkly
|
|
142
145
|
items[key] = Model.deserialize(kind, item)
|
143
146
|
end
|
144
147
|
|
145
|
-
def make_flag_with_value(key, value)
|
148
|
+
def make_flag_with_value(key, value, version)
|
146
149
|
{
|
147
150
|
key: key,
|
148
151
|
on: true,
|
152
|
+
version: version,
|
149
153
|
fallthrough: { variation: 0 },
|
150
154
|
variations: [ value ],
|
151
155
|
}
|
@@ -93,7 +93,7 @@ module LaunchDarkly
|
|
93
93
|
# Note that the default implementation of this feature is based on polling the filesystem,
|
94
94
|
# which may not perform well. If you install the 'listen' gem (not included by default, to
|
95
95
|
# avoid adding unwanted dependencies to the SDK), its native file watching mechanism will be
|
96
|
-
# used instead.
|
96
|
+
# used instead.
|
97
97
|
# @option options [Float] :poll_interval The minimum interval, in seconds, between checks for
|
98
98
|
# file modifications - used only if auto_update is true, and if the native file-watching
|
99
99
|
# mechanism from 'listen' is not being used. The default value is 1 second.
|
data/lib/ldclient-rb/ldclient.rb
CHANGED
@@ -124,13 +124,18 @@ module LaunchDarkly
|
|
124
124
|
end
|
125
125
|
|
126
126
|
ready = @data_source.start
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
127
|
+
|
128
|
+
return unless wait_for_sec > 0
|
129
|
+
|
130
|
+
if wait_for_sec > 60
|
131
|
+
@config.logger.warn { "[LDClient] Client was configured to block for up to #{wait_for_sec} seconds when initializing. We recommend blocking no longer than 60." }
|
132
|
+
end
|
133
|
+
|
134
|
+
ok = ready.wait(wait_for_sec)
|
135
|
+
if !ok
|
136
|
+
@config.logger.error { "[LDClient] Timeout encountered waiting for LaunchDarkly client initialization" }
|
137
|
+
elsif !@data_source.initialized?
|
138
|
+
@config.logger.error { "[LDClient] LaunchDarkly client initialization failed" }
|
134
139
|
end
|
135
140
|
end
|
136
141
|
|
@@ -238,6 +238,16 @@ module LaunchDarkly
|
|
238
238
|
([error] + components).hash
|
239
239
|
end
|
240
240
|
|
241
|
+
#
|
242
|
+
# Convert the Reference to a JSON string.
|
243
|
+
#
|
244
|
+
# @param args [Array]
|
245
|
+
# @return [String]
|
246
|
+
#
|
247
|
+
def to_json(*args)
|
248
|
+
JSON.generate(@raw_path, *args)
|
249
|
+
end
|
250
|
+
|
241
251
|
#
|
242
252
|
# Performs unescaping of attribute reference path components:
|
243
253
|
#
|
data/lib/ldclient-rb/version.rb
CHANGED
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: 8.
|
4
|
+
version: 8.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- LaunchDarkly
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-dynamodb
|
@@ -376,7 +376,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
376
376
|
- !ruby/object:Gem::Version
|
377
377
|
version: '0'
|
378
378
|
requirements: []
|
379
|
-
rubygems_version: 3.5.
|
379
|
+
rubygems_version: 3.5.11
|
380
380
|
signing_key:
|
381
381
|
specification_version: 4
|
382
382
|
summary: LaunchDarkly SDK for Ruby
|