launchdarkly-server-sdk 8.1.0 → 8.4.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: 133fe555993b53f1e53f3348242d1c96ac2318d2c2c1ebf48e33e4d23c6e97f3
4
- data.tar.gz: 12f604c2a17d9d06433a1ad041051e41f767efa3c7310a5925553cb5678b5709
3
+ metadata.gz: c04f38ba70b95c1446fc0aaffd2f3020e208501e9ede2313b559848792c1bf81
4
+ data.tar.gz: 6dd37514e2588d78c995702af1d66d6f00cdc3762ce4908690a2a4e13ab5c46d
5
5
  SHA512:
6
- metadata.gz: 1be2d4708681d7e0a2665e68e878ed8d2e17975f6c28716ed139911b866acb067884b4af872e6f5469177f09b5071f1c8fbb0ac6b7519f581bb20ee11afb76df
7
- data.tar.gz: 2d0a5df44d5de21887eb4330f34bf65d4a4bab9a153d7644077790e3262a8b6418c26c4ebe5612523be468d05ddd5a8b837dc22a347c08ef463229c337e040c3
6
+ metadata.gz: 40f20870dfa777687da11f7611255ee7f15dde800c7ac9860e5a673643c9d7d19841932162fcabef1d57e6a9ab7710fb3d06ea72567336a5c26ecb0cdd220f74
7
+ data.tar.gz: bbf303fc081003f0a5e71f2fd38dc48f707958c5c33f6f450982db6c3fecb7076f287460d597414b52c8e4181d95c55babd599fca7877bebe4ff9d82d38e6dd5
data/README.md CHANGED
@@ -39,7 +39,12 @@ Contributing
39
39
  ------------
40
40
 
41
41
  We encourage pull requests and other contributions from the community. Check out our [contributing guidelines](CONTRIBUTING.md) for instructions on how to contribute to this SDK.
42
-
42
+
43
+ Verifying SDK build provenance with the SLSA framework
44
+ ------------
45
+
46
+ LaunchDarkly uses the [SLSA framework](https://slsa.dev/spec/v1.0/about) (Supply-chain Levels for Software Artifacts) to help developers make their supply chain more secure by ensuring the authenticity and build integrity of our published SDK packages. To learn more, see the [provenance guide](PROVENANCE.md).
47
+
43
48
  About LaunchDarkly
44
49
  -----------
45
50
 
@@ -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 hooks [Array<Interfaces::Hooks::Hook]
46
47
  #
47
48
  def initialize(opts = {})
48
49
  @base_uri = (opts[:base_uri] || Config.default_base_uri).chomp("/")
@@ -75,6 +76,7 @@ module LaunchDarkly
75
76
  @big_segments = opts[:big_segments] || BigSegmentsConfig.new(store: nil)
76
77
  @application = LaunchDarkly::Impl::Util.validate_application_info(opts[:application] || {}, @logger)
77
78
  @payload_filter_key = opts[:payload_filter_key]
79
+ @hooks = (opts[:hooks] || []).keep_if { |hook| hook.is_a? Interfaces::Hooks::Hook }
78
80
  @data_source_update_sink = nil
79
81
  end
80
82
 
@@ -372,6 +374,17 @@ module LaunchDarkly
372
374
  #
373
375
  attr_reader :socket_factory
374
376
 
377
+ #
378
+ # Initial set of hooks for the client.
379
+ #
380
+ # Hooks provide entrypoints which allow for observation of SDK functions.
381
+ #
382
+ # LaunchDarkly provides integration packages, and most applications will not
383
+ # need to implement their own hooks. Refer to the `launchdarkly-server-sdk-otel` gem
384
+ # for instrumentation.
385
+ #
386
+ attr_reader :hooks
387
+
375
388
  #
376
389
  # The default LaunchDarkly client configuration. This configuration sets
377
390
  # reasonable defaults for most users.
@@ -458,7 +471,7 @@ module LaunchDarkly
458
471
  # @return [Logger] the Rails logger if in Rails, or a default Logger at WARN level otherwise
459
472
  #
460
473
  def self.default_logger
461
- if defined?(Rails) && Rails.respond_to?(:logger)
474
+ if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
462
475
  Rails.logger
463
476
  else
464
477
  log = ::Logger.new($stdout)
@@ -377,8 +377,6 @@ module LaunchDarkly
377
377
  # {https://docs.launchdarkly.com/sdk/features/user-config SDK
378
378
  # documentation}.
379
379
  #
380
- # @deprecated The old user format will be removed in 8.0.0. Please use the new context specific format.
381
- #
382
380
  # @param data [Hash]
383
381
  # @return [LDContext]
384
382
  #
@@ -481,12 +481,14 @@ module LaunchDarkly
481
481
  key: event.key,
482
482
  value: event.value,
483
483
  }
484
+
484
485
  out[:default] = event.default unless event.default.nil?
485
486
  out[:variation] = event.variation unless event.variation.nil?
486
487
  out[:version] = event.version unless event.version.nil?
487
488
  out[:prereqOf] = event.prereq_of unless event.prereq_of.nil?
488
- out[:contextKeys] = event.context.keys
489
+ out[:context] = @context_filter.filter_redact_anonymous(event.context)
489
490
  out[:reason] = event.reason unless event.reason.nil?
491
+
490
492
  out
491
493
 
492
494
  when LaunchDarkly::Impl::MigrationOpEvent
@@ -23,14 +23,32 @@ module LaunchDarkly
23
23
  # @return [Hash]
24
24
  #
25
25
  def filter(context)
26
- return filter_single_context(context, true) unless context.multi_kind?
26
+ internal_filter(context, false)
27
+ end
28
+
29
+ #
30
+ # Return a hash representation of the provided context with attribute
31
+ # redaction applied.
32
+ #
33
+ # If a context is anonyomous, all attributes will be redacted except
34
+ # for key, kind, and anonymous.
35
+ #
36
+ # @param context [LaunchDarkly::LDContext]
37
+ # @return [Hash]
38
+ #
39
+ def filter_redact_anonymous(context)
40
+ internal_filter(context, true)
41
+ end
42
+
43
+ private def internal_filter(context, redact_anonymous)
44
+ return filter_single_context(context, true, redact_anonymous) unless context.multi_kind?
27
45
 
28
46
  filtered = {kind: 'multi'}
29
47
  (0...context.individual_context_count).each do |i|
30
48
  c = context.individual_context(i)
31
49
  next if c.nil?
32
50
 
33
- filtered[c.kind] = filter_single_context(c, false)
51
+ filtered[c.kind] = filter_single_context(c, false, redact_anonymous)
34
52
  end
35
53
 
36
54
  filtered
@@ -43,22 +61,24 @@ module LaunchDarkly
43
61
  # @param include_kind [Boolean]
44
62
  # @return [Hash]
45
63
  #
46
- private def filter_single_context(context, include_kind)
64
+ private def filter_single_context(context, include_kind, redact_anonymous)
47
65
  filtered = {key: context.key}
48
66
 
49
67
  filtered[:kind] = context.kind if include_kind
50
- filtered[:anonymous] = true if context.get_value(:anonymous)
68
+
69
+ anonymous = context.get_value(:anonymous)
70
+ filtered[:anonymous] = true if anonymous
51
71
 
52
72
  redacted = []
53
73
  private_attributes = @private_attributes.concat(context.private_attributes)
54
74
 
55
75
  name = context.get_value(:name)
56
- if !name.nil? && !check_whole_attribute_private(:name, private_attributes, redacted)
76
+ if !name.nil? && !check_whole_attribute_private(:name, private_attributes, redacted, anonymous && redact_anonymous)
57
77
  filtered[:name] = name
58
78
  end
59
79
 
60
80
  context.get_custom_attribute_names.each do |attribute|
61
- unless check_whole_attribute_private(attribute, private_attributes, redacted)
81
+ unless check_whole_attribute_private(attribute, private_attributes, redacted, anonymous && redact_anonymous)
62
82
  value = context.get_value(attribute)
63
83
  filtered[attribute] = redact_json_value(nil, attribute, value, private_attributes, redacted)
64
84
  end
@@ -75,10 +95,11 @@ module LaunchDarkly
75
95
  # @param attribute [Symbol]
76
96
  # @param private_attributes [Array<Reference>]
77
97
  # @param redacted [Array<Symbol>]
98
+ # @param redact_all [Boolean]
78
99
  # @return [Boolean]
79
100
  #
80
- private def check_whole_attribute_private(attribute, private_attributes, redacted)
81
- if @all_attributes_private
101
+ private def check_whole_attribute_private(attribute, private_attributes, redacted, redact_all)
102
+ if @all_attributes_private || redact_all
82
103
  redacted << attribute
83
104
  return true
84
105
  end
@@ -0,0 +1,34 @@
1
+ module LaunchDarkly
2
+ module Impl
3
+ #
4
+ # Simple helper class for returning formatted data.
5
+ #
6
+ # The variation methods make use of the new hook support. Those methods all need to return an evaluation detail, and
7
+ # some other unstructured bit of data.
8
+ #
9
+ class EvaluationWithHookResult
10
+ #
11
+ # Return the evaluation detail that was generated as part of the evaluation.
12
+ #
13
+ # @return [LaunchDarkly::EvaluationDetail]
14
+ #
15
+ attr_reader :evaluation_detail
16
+
17
+ #
18
+ # All purpose container for additional return values from the wrapping method
19
+ #
20
+ # @return [any]
21
+ #
22
+ attr_reader :results
23
+
24
+ #
25
+ # @param evaluation_detail [LaunchDarkly::EvaluationDetail]
26
+ # @param results [any]
27
+ #
28
+ def initialize(evaluation_detail, results = nil)
29
+ @evaluation_detail = evaluation_detail
30
+ @results = results
31
+ end
32
+ end
33
+ end
34
+ end
@@ -37,7 +37,7 @@ module LaunchDarkly
37
37
  @off_variation = data[:offVariation]
38
38
  check_variation_range(self, errors, @off_variation, "off variation")
39
39
  @prerequisites = (data[:prerequisites] || []).map do |prereq_data|
40
- Prerequisite.new(prereq_data, self, errors)
40
+ Prerequisite.new(prereq_data, self)
41
41
  end
42
42
  @targets = (data[:targets] || []).map do |target_data|
43
43
  Target.new(target_data, self, errors)
@@ -118,13 +118,12 @@ module LaunchDarkly
118
118
  end
119
119
 
120
120
  class Prerequisite
121
- def initialize(data, flag, errors_out = nil)
121
+ def initialize(data, flag)
122
122
  @data = data
123
123
  @key = data[:key]
124
124
  @variation = data[:variation]
125
125
  @failure_result = EvaluatorHelpers.evaluation_detail_for_off_variation(flag,
126
126
  EvaluationReason::prerequisite_failed(@key))
127
- check_variation_range(flag, errors_out, @variation, "prerequisite")
128
127
  end
129
128
 
130
129
  # @return [Hash]
@@ -885,5 +885,90 @@ module LaunchDarkly
885
885
  end
886
886
  end
887
887
  end
888
+
889
+ module Hooks
890
+ #
891
+ # Mixin for extending SDK functionality via hooks.
892
+ #
893
+ # All provided hook implementations **MUST** include this mixin. Hooks without this mixin will be ignored.
894
+ #
895
+ # This mixin includes default implementations for all hook handlers. This allows LaunchDarkly to expand the list
896
+ # of hook handlers without breaking customer integrations.
897
+ #
898
+ module Hook
899
+ #
900
+ # Get metadata about the hook implementation.
901
+ #
902
+ # @return [Metadata]
903
+ #
904
+ def metadata
905
+ Metadata.new('UNDEFINED')
906
+ end
907
+
908
+ #
909
+ # The before method is called during the execution of a variation method before the flag value has been
910
+ # determined. The method is executed synchronously.
911
+ #
912
+ # @param evaluation_series_context [EvaluationSeriesContext] Contains information about the evaluation being
913
+ # performed. This is not mutable.
914
+ # @param data [Hash] A record associated with each stage of hook invocations. Each stage is called with the data
915
+ # of the previous stage for a series. The input record should not be modified.
916
+ # @return [Hash] Data to use when executing the next state of the hook in the evaluation series.
917
+ #
918
+ def before_evaluation(evaluation_series_context, data)
919
+ data
920
+ end
921
+
922
+ #
923
+ # The after method is called during the execution of the variation method after the flag value has been
924
+ # determined. The method is executed synchronously.
925
+ #
926
+ # @param evaluation_series_context [EvaluationSeriesContext] Contains read-only information about the evaluation
927
+ # being performed.
928
+ # @param data [Hash] A record associated with each stage of hook invocations. Each stage is called with the data
929
+ # of the previous stage for a series.
930
+ # @param detail [LaunchDarkly::EvaluationDetail] The result of the evaluation. This value should not be
931
+ # modified.
932
+ # @return [Hash] Data to use when executing the next state of the hook in the evaluation series.
933
+ #
934
+ def after_evaluation(evaluation_series_context, data, detail)
935
+ data
936
+ end
937
+ end
938
+
939
+ #
940
+ # Metadata data class used for annotating hook implementations.
941
+ #
942
+ class Metadata
943
+ attr_reader :name
944
+
945
+ def initialize(name)
946
+ @name = name
947
+ end
948
+ end
949
+
950
+ #
951
+ # Contextual information that will be provided to handlers during evaluation series.
952
+ #
953
+ class EvaluationSeriesContext
954
+ attr_reader :key
955
+ attr_reader :context
956
+ attr_reader :default_value
957
+ attr_reader :method
958
+
959
+ #
960
+ # @param key [String]
961
+ # @param context [LaunchDarkly::LDContext]
962
+ # @param default_value [any]
963
+ # @param method [Symbol]
964
+ #
965
+ def initialize(key, context, default_value, method)
966
+ @key = key
967
+ @context = context
968
+ @default_value = default_value
969
+ @method = method
970
+ end
971
+ end
972
+ end
888
973
  end
889
974
  end
@@ -4,9 +4,11 @@ require "ldclient-rb/impl/data_source"
4
4
  require "ldclient-rb/impl/data_store"
5
5
  require "ldclient-rb/impl/diagnostic_events"
6
6
  require "ldclient-rb/impl/evaluator"
7
+ require "ldclient-rb/impl/evaluation_with_hook_result"
7
8
  require "ldclient-rb/impl/flag_tracker"
8
9
  require "ldclient-rb/impl/store_client_wrapper"
9
10
  require "ldclient-rb/impl/migrations/tracker"
11
+ require "concurrent"
10
12
  require "concurrent/atomics"
11
13
  require "digest/sha1"
12
14
  require "forwardable"
@@ -54,6 +56,7 @@ module LaunchDarkly
54
56
  end
55
57
 
56
58
  @sdk_key = sdk_key
59
+ @hooks = Concurrent::Array.new(config.hooks)
57
60
 
58
61
  @shared_executor = Concurrent::SingleThreadExecutor.new
59
62
 
@@ -131,6 +134,23 @@ module LaunchDarkly
131
134
  end
132
135
  end
133
136
 
137
+ #
138
+ # Add a hook to the client. In order to register a hook before the client starts, please use the `hooks` property of
139
+ # {#LDConfig}.
140
+ #
141
+ # Hooks provide entrypoints which allow for observation of SDK functions.
142
+ #
143
+ # @param hook [Interfaces::Hooks::Hook]
144
+ #
145
+ def add_hook(hook)
146
+ unless hook.is_a?(Interfaces::Hooks::Hook)
147
+ @config.logger.error { "[LDClient] Attempted to add a hook that does not include the LaunchDarkly::Intefaces::Hooks::Hook mixin. Ignoring." }
148
+ return
149
+ end
150
+
151
+ @hooks.push(hook)
152
+ end
153
+
134
154
  #
135
155
  # Tells the client that all pending analytics events should be delivered as soon as possible.
136
156
  #
@@ -198,8 +218,13 @@ module LaunchDarkly
198
218
  # @return the variation for the provided context, or the default value if there's an error
199
219
  #
200
220
  def variation(key, context, default)
201
- detail, _, _, = variation_with_flag(key, context, default)
202
- detail.value
221
+ context = Impl::Context::make_context(context)
222
+ result = evaluate_with_hooks(key, context, default, :variation) do
223
+ detail, _, _ = variation_with_flag(key, context, default)
224
+ LaunchDarkly::Impl::EvaluationWithHookResult.new(detail)
225
+ end
226
+
227
+ result.evaluation_detail.value
203
228
  end
204
229
 
205
230
  #
@@ -226,8 +251,118 @@ module LaunchDarkly
226
251
  # @return [EvaluationDetail] an object describing the result
227
252
  #
228
253
  def variation_detail(key, context, default)
229
- detail, _, _ = evaluate_internal(key, context, default, true)
230
- detail
254
+ context = Impl::Context::make_context(context)
255
+ result = evaluate_with_hooks(key, context, default, :variation_detail) do
256
+ detail, _, _ = evaluate_internal(key, context, default, true)
257
+ LaunchDarkly::Impl::EvaluationWithHookResult.new(detail)
258
+ end
259
+
260
+ result.evaluation_detail
261
+ end
262
+
263
+ #
264
+ # evaluate_with_hook will run the provided block, wrapping it with evaluation hook support.
265
+ #
266
+ # Example:
267
+ #
268
+ # ```ruby
269
+ # evaluate_with_hooks(key, context, default, method) do
270
+ # puts 'This is being wrapped with evaluation hooks'
271
+ # end
272
+ # ```
273
+ #
274
+ # @param key [String]
275
+ # @param context [LDContext]
276
+ # @param default [any]
277
+ # @param method [Symbol]
278
+ # @param &block [#call] Implicit passed block
279
+ #
280
+ # @return [LaunchDarkly::Impl::EvaluationWithHookResult]
281
+ #
282
+ private def evaluate_with_hooks(key, context, default, method)
283
+ return yield if @hooks.empty?
284
+
285
+ hooks, evaluation_series_context = prepare_hooks(key, context, default, method)
286
+ hook_data = execute_before_evaluation(hooks, evaluation_series_context)
287
+ evaluation_result = yield
288
+ execute_after_evaluation(hooks, evaluation_series_context, hook_data, evaluation_result.evaluation_detail)
289
+
290
+ evaluation_result
291
+ end
292
+
293
+ #
294
+ # Execute the :before_evaluation stage of the evaluation series.
295
+ #
296
+ # This method will return the results of each hook, indexed into an array in the same order as the hooks. If a hook
297
+ # raised an uncaught exception, the value will be nil.
298
+ #
299
+ # @param hooks [Array<Interfaces::Hooks::Hook>]
300
+ # @param evaluation_series_context [EvaluationSeriesContext]
301
+ #
302
+ # @return [Array<any>]
303
+ #
304
+ private def execute_before_evaluation(hooks, evaluation_series_context)
305
+ hooks.map do |hook|
306
+ try_execute_stage(:before_evaluation, hook.metadata.name) do
307
+ hook.before_evaluation(evaluation_series_context, {})
308
+ end
309
+ end
310
+ end
311
+
312
+ #
313
+ # Execute the :after_evaluation stage of the evaluation series.
314
+ #
315
+ # This method will return the results of each hook, indexed into an array in the same order as the hooks. If a hook
316
+ # raised an uncaught exception, the value will be nil.
317
+ #
318
+ # @param hooks [Array<Interfaces::Hooks::Hook>]
319
+ # @param evaluation_series_context [EvaluationSeriesContext]
320
+ # @param hook_data [Array<any>]
321
+ # @param evaluation_detail [EvaluationDetail]
322
+ #
323
+ # @return [Array<any>]
324
+ #
325
+ private def execute_after_evaluation(hooks, evaluation_series_context, hook_data, evaluation_detail)
326
+ hooks.zip(hook_data).reverse.map do |(hook, data)|
327
+ try_execute_stage(:after_evaluation, hook.metadata.name) do
328
+ hook.after_evaluation(evaluation_series_context, data, evaluation_detail)
329
+ end
330
+ end
331
+ end
332
+
333
+ #
334
+ # Try to execute the provided block. If execution raises an exception, catch and log it, then move on with
335
+ # execution.
336
+ #
337
+ # @return [any]
338
+ #
339
+ private def try_execute_stage(method, hook_name)
340
+ begin
341
+ yield
342
+ rescue => e
343
+ @config.logger.error { "[LDClient] An error occurred in #{method} of the hook #{hook_name}: #{e}" }
344
+ nil
345
+ end
346
+ end
347
+
348
+ #
349
+ # Return a copy of the existing hooks and a few instance of the EvaluationSeriesContext used for the evaluation series.
350
+ #
351
+ # @param key [String]
352
+ # @param context [LDContext]
353
+ # @param default [any]
354
+ # @param method [Symbol]
355
+ # @return [Array[Array<Interfaces::Hooks::Hook>, Interfaces::Hooks::EvaluationSeriesContext]]
356
+ #
357
+ private def prepare_hooks(key, context, default, method)
358
+ # Copy the hooks to use a consistent set during the evaluation series.
359
+ #
360
+ # Hooks can be added and we want to ensure all correct stages for a given hook execute. For example, we do not
361
+ # want to trigger the after_evaluation method without also triggering the before_evaluation method.
362
+ hooks = @hooks.dup
363
+ evaluation_series_context = Interfaces::Hooks::EvaluationSeriesContext.new(key, context, default, method)
364
+
365
+ [hooks, evaluation_series_context]
231
366
  end
232
367
 
233
368
  #
@@ -249,20 +384,24 @@ module LaunchDarkly
249
384
  end
250
385
 
251
386
  context = Impl::Context::make_context(context)
252
- detail, flag, _ = variation_with_flag(key, context, default_stage.to_s)
387
+ result = evaluate_with_hooks(key, context, default_stage, :migration_variation) do
388
+ detail, flag, _ = variation_with_flag(key, context, default_stage.to_s)
253
389
 
254
- stage = detail.value
255
- stage = stage.to_sym if stage.respond_to? :to_sym
390
+ stage = detail.value
391
+ stage = stage.to_sym if stage.respond_to? :to_sym
256
392
 
257
- if Migrations::VALID_STAGES.include?(stage)
393
+ if Migrations::VALID_STAGES.include?(stage)
394
+ tracker = Impl::Migrations::OpTracker.new(@config.logger, key, flag, context, detail, default_stage)
395
+ next LaunchDarkly::Impl::EvaluationWithHookResult.new(detail, {stage: stage, tracker: tracker})
396
+ end
397
+
398
+ detail = LaunchDarkly::Impl::Evaluator.error_result(LaunchDarkly::EvaluationReason::ERROR_WRONG_TYPE, default_stage.to_s)
258
399
  tracker = Impl::Migrations::OpTracker.new(@config.logger, key, flag, context, detail, default_stage)
259
- return stage, tracker
260
- end
261
400
 
262
- detail = LaunchDarkly::Impl::Evaluator.error_result(LaunchDarkly::EvaluationReason::ERROR_WRONG_TYPE, default_stage.to_s)
263
- tracker = Impl::Migrations::OpTracker.new(@config.logger, key, flag, context, detail, default_stage)
401
+ LaunchDarkly::Impl::EvaluationWithHookResult.new(detail, {stage: default_stage, tracker: tracker})
402
+ end
264
403
 
265
- [default_stage, tracker]
404
+ [result.results[:stage], result.results[:tracker]]
266
405
  end
267
406
 
268
407
  #
@@ -502,7 +641,7 @@ module LaunchDarkly
502
641
 
503
642
  #
504
643
  # @param key [String]
505
- # @param context [Hash, LDContext]
644
+ # @param context [LDContext]
506
645
  # @param default [Object]
507
646
  #
508
647
  # @return [Array<EvaluationDetail, [LaunchDarkly::Impl::Model::FeatureFlag, nil], [String, nil]>]
@@ -513,7 +652,7 @@ module LaunchDarkly
513
652
 
514
653
  #
515
654
  # @param key [String]
516
- # @param context [Hash, LDContext]
655
+ # @param context [LDContext]
517
656
  # @param default [Object]
518
657
  # @param with_reasons [Boolean]
519
658
  #
@@ -530,7 +669,6 @@ module LaunchDarkly
530
669
  return detail, nil, "no context provided"
531
670
  end
532
671
 
533
- context = Impl::Context::make_context(context)
534
672
  unless context.valid?
535
673
  @config.logger.error { "[LDClient] Context was invalid for evaluation of flag '#{key}' (#{context.error}); returning default value" }
536
674
  detail = Evaluator.error_result(EvaluationReason::ERROR_USER_NOT_SPECIFIED, default)
@@ -26,6 +26,8 @@ module LaunchDarkly
26
26
  @sdk_key = sdk_key
27
27
  @config = config
28
28
  @http_client = LaunchDarkly::Util.new_http_client(config.base_uri, config)
29
+ .use(:auto_inflate)
30
+ .headers("Accept-Encoding" => "gzip")
29
31
  @cache = @config.cache_store
30
32
  end
31
33
 
@@ -1,3 +1,3 @@
1
1
  module LaunchDarkly
2
- VERSION = "8.1.0" # x-release-please-version
2
+ VERSION = "8.4.2" # x-release-please-version
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: 8.1.0
4
+ version: 8.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - LaunchDarkly
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-03 00:00:00.000000000 Z
11
+ date: 2024-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-dynamodb
@@ -234,6 +234,20 @@ dependencies:
234
234
  - - '='
235
235
  - !ruby/object:Gem::Version
236
236
  version: 2.2.2
237
+ - !ruby/object:Gem::Dependency
238
+ name: observer
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - "~>"
242
+ - !ruby/object:Gem::Version
243
+ version: 0.1.2
244
+ type: :runtime
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - "~>"
249
+ - !ruby/object:Gem::Version
250
+ version: 0.1.2
237
251
  - !ruby/object:Gem::Dependency
238
252
  name: json
239
253
  requirement: !ruby/object:Gem::Requirement
@@ -295,6 +309,7 @@ files:
295
309
  - lib/ldclient-rb/impl/data_store.rb
296
310
  - lib/ldclient-rb/impl/dependency_tracker.rb
297
311
  - lib/ldclient-rb/impl/diagnostic_events.rb
312
+ - lib/ldclient-rb/impl/evaluation_with_hook_result.rb
298
313
  - lib/ldclient-rb/impl/evaluator.rb
299
314
  - lib/ldclient-rb/impl/evaluator_bucketing.rb
300
315
  - lib/ldclient-rb/impl/evaluator_helpers.rb
@@ -361,7 +376,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
361
376
  - !ruby/object:Gem::Version
362
377
  version: '0'
363
378
  requirements: []
364
- rubygems_version: 3.5.3
379
+ rubygems_version: 3.5.9
365
380
  signing_key:
366
381
  specification_version: 4
367
382
  summary: LaunchDarkly SDK for Ruby