launchdarkly-server-sdk 8.11.1 → 8.11.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: e13dd73f598b3c784c48f2f1d935bff9ac8211717dbaa224b9cf856d909ea054
4
- data.tar.gz: 53e5f7b84ff83e6770aa8f49e7b972c452fde3625168f95efa1569b9310b4266
3
+ metadata.gz: e0821343a2375748e37f95a7a43016973a21c6027d9f0b3c402074ae9859c91b
4
+ data.tar.gz: d285b359f653ed6ea74d9b6fedd8ff0388347e24d986f72866c226b24516ed38
5
5
  SHA512:
6
- metadata.gz: d6c290d83db944daebe948c1d799668010c1e879d4986e377298a28abc87e046f9c23051c830a80ac7422f6cfb62ed9025c4f224e693f0be36dbc63073ed15c6
7
- data.tar.gz: 26ba1dd07b32763589eeaf7c9f55b53105dce4b7da2fc73430927646f27c1e2756d3feaa2608aa7adec7481876ec6661c6af0ceee2b58ac32ece35765306723a
6
+ metadata.gz: e9937a4267ca69970169b66564e1fdfff11e7ceefa57462a0f4f11830aa6ef8cefc34dbcb83e62910759c14ba3120d53c20ba7436d87f21aff0a63ad2996ff8f
7
+ data.tar.gz: 6726a6c125e3253c691d8c566e46ef17dc29cfb76407e79232f9b213580bfc53665bf1968fc60b48641a93276b8b4bd6c2bdabce77bda70f4575df2e5b61ec11
@@ -231,7 +231,7 @@ module LaunchDarkly
231
231
  def initialize(inbox, sdk_key, config, diagnostic_accumulator, event_sender)
232
232
  @sdk_key = sdk_key
233
233
  @config = config
234
- @diagnostic_accumulator = config.diagnostic_opt_out? ? nil : diagnostic_accumulator
234
+ @diagnostic_accumulator = diagnostic_accumulator
235
235
  @event_sender = event_sender
236
236
  @sampler = LaunchDarkly::Impl::Sampler.new(Random.new)
237
237
 
@@ -0,0 +1,52 @@
1
+ require 'concurrent'
2
+ require 'ldclient-rb/interfaces'
3
+
4
+ module LaunchDarkly
5
+ module Impl
6
+ module DataSource
7
+ #
8
+ # A minimal UpdateProcessor implementation used when the SDK is in offline mode
9
+ # or daemon (LDD) mode. It does nothing except mark itself as initialized.
10
+ #
11
+ class NullUpdateProcessor
12
+ include LaunchDarkly::Interfaces::DataSource
13
+
14
+ #
15
+ # Creates a new NullUpdateProcessor.
16
+ #
17
+ def initialize
18
+ @ready = Concurrent::Event.new
19
+ end
20
+
21
+ #
22
+ # Starts the data source. Since this is a null implementation, it immediately
23
+ # sets the ready event to indicate initialization is complete.
24
+ #
25
+ # @return [Concurrent::Event] The ready event
26
+ #
27
+ def start
28
+ @ready.set
29
+ @ready
30
+ end
31
+
32
+ #
33
+ # Stops the data source. This is a no-op for the null implementation.
34
+ #
35
+ # @return [void]
36
+ #
37
+ def stop
38
+ # Nothing to do
39
+ end
40
+
41
+ #
42
+ # Checks if the data source has been initialized.
43
+ #
44
+ # @return [Boolean] Always returns true since this is a null implementation
45
+ #
46
+ def initialized?
47
+ true
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,165 @@
1
+ require 'concurrent'
2
+ require 'ldclient-rb/impl/broadcaster'
3
+ require 'ldclient-rb/impl/data_source'
4
+ require 'ldclient-rb/impl/data_source/null_processor'
5
+ require 'ldclient-rb/impl/data_store'
6
+ require 'ldclient-rb/impl/data_system'
7
+ require 'ldclient-rb/impl/store_client_wrapper'
8
+
9
+ module LaunchDarkly
10
+ module Impl
11
+ module DataSystem
12
+ #
13
+ # FDv1 wires the existing v1 data source and store behavior behind the
14
+ # generic DataSystem surface.
15
+ #
16
+ # @see DataSystem
17
+ #
18
+ class FDv1
19
+ include LaunchDarkly::Impl::DataSystem
20
+
21
+ #
22
+ # Creates a new FDv1 data system.
23
+ #
24
+ # @param sdk_key [String] The SDK key
25
+ # @param config [LaunchDarkly::Config] The SDK configuration
26
+ #
27
+ def initialize(sdk_key, config)
28
+ @sdk_key = sdk_key
29
+ @config = config
30
+ @shared_executor = Concurrent::SingleThreadExecutor.new
31
+
32
+ # Set up data store plumbing
33
+ @data_store_broadcaster = LaunchDarkly::Impl::Broadcaster.new(@shared_executor, @config.logger)
34
+ @data_store_update_sink = LaunchDarkly::Impl::DataStore::UpdateSink.new(
35
+ @data_store_broadcaster
36
+ )
37
+
38
+ # Wrap the data store with client wrapper (must be created before status provider)
39
+ @store_wrapper = LaunchDarkly::Impl::FeatureStoreClientWrapper.new(
40
+ @config.feature_store,
41
+ @data_store_update_sink,
42
+ @config.logger
43
+ )
44
+
45
+ # Create status provider with store wrapper
46
+ @data_store_status_provider = LaunchDarkly::Impl::DataStore::StatusProvider.new(
47
+ @store_wrapper,
48
+ @data_store_update_sink
49
+ )
50
+
51
+ # Set up data source plumbing
52
+ @data_source_broadcaster = LaunchDarkly::Impl::Broadcaster.new(@shared_executor, @config.logger)
53
+ @flag_change_broadcaster = LaunchDarkly::Impl::Broadcaster.new(@shared_executor, @config.logger)
54
+ @data_source_update_sink = LaunchDarkly::Impl::DataSource::UpdateSink.new(
55
+ @store_wrapper,
56
+ @data_source_broadcaster,
57
+ @flag_change_broadcaster
58
+ )
59
+ @data_source_status_provider = LaunchDarkly::Impl::DataSource::StatusProvider.new(
60
+ @data_source_broadcaster,
61
+ @data_source_update_sink
62
+ )
63
+
64
+ # Ensure v1 processors can find the sink via config for status updates
65
+ @config.data_source_update_sink = @data_source_update_sink
66
+
67
+ # Update processor created in start()
68
+ @update_processor = nil
69
+
70
+ # Diagnostic accumulator provided by client for streaming metrics
71
+ @diagnostic_accumulator = nil
72
+ end
73
+
74
+ # (see DataSystem#start)
75
+ def start
76
+ @update_processor ||= make_update_processor
77
+ @update_processor.start
78
+ end
79
+
80
+ # (see DataSystem#stop)
81
+ def stop
82
+ @update_processor&.stop
83
+ @shared_executor.shutdown
84
+ end
85
+
86
+ # (see DataSystem#store)
87
+ def store
88
+ @store_wrapper
89
+ end
90
+
91
+ # (see DataSystem#set_diagnostic_accumulator)
92
+ def set_diagnostic_accumulator(diagnostic_accumulator)
93
+ @diagnostic_accumulator = diagnostic_accumulator
94
+ end
95
+
96
+ # (see DataSystem#data_source_status_provider)
97
+ def data_source_status_provider
98
+ @data_source_status_provider
99
+ end
100
+
101
+ # (see DataSystem#data_store_status_provider)
102
+ def data_store_status_provider
103
+ @data_store_status_provider
104
+ end
105
+
106
+ # (see DataSystem#flag_change_broadcaster)
107
+ def flag_change_broadcaster
108
+ @flag_change_broadcaster
109
+ end
110
+
111
+ #
112
+ # (see DataSystem#data_availability)
113
+ #
114
+ # In LDD mode, always returns CACHED for backwards compatibility,
115
+ # even if the store is empty.
116
+ #
117
+ def data_availability
118
+ return DataAvailability::DEFAULTS if @config.offline?
119
+ return DataAvailability::REFRESHED if @update_processor && @update_processor.initialized?
120
+ return DataAvailability::CACHED if @store_wrapper.initialized?
121
+
122
+ DataAvailability::DEFAULTS
123
+ end
124
+
125
+ # (see DataSystem#target_availability)
126
+ def target_availability
127
+ return DataAvailability::DEFAULTS if @config.offline?
128
+
129
+ DataAvailability::REFRESHED
130
+ end
131
+
132
+ #
133
+ # Creates the appropriate update processor based on the configuration.
134
+ #
135
+ # @return [Object] The update processor
136
+ #
137
+ private def make_update_processor
138
+ # Handle custom data source (factory or instance)
139
+ if @config.data_source
140
+ return @config.data_source unless @config.data_source.respond_to?(:call)
141
+
142
+ # Factory - call with appropriate arity
143
+ return @config.data_source.arity == 3 ?
144
+ @config.data_source.call(@sdk_key, @config, @diagnostic_accumulator) :
145
+ @config.data_source.call(@sdk_key, @config)
146
+ end
147
+
148
+ # Create default data source based on config
149
+ return LaunchDarkly::Impl::DataSource::NullUpdateProcessor.new if @config.offline? || @config.use_ldd?
150
+
151
+ if @config.stream?
152
+ require 'ldclient-rb/stream'
153
+ return LaunchDarkly::StreamProcessor.new(@sdk_key, @config, @diagnostic_accumulator)
154
+ end
155
+
156
+ # Polling processor
157
+ require 'ldclient-rb/polling'
158
+ requestor = LaunchDarkly::Requestor.new(@sdk_key, @config)
159
+ LaunchDarkly::PollingProcessor.new(@config, requestor)
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+
@@ -0,0 +1,298 @@
1
+ module LaunchDarkly
2
+ module Impl
3
+ #
4
+ # Mixin that defines the required methods of a data system implementation. The data system
5
+ # is responsible for managing the SDK's data model, including storage, retrieval, and change
6
+ # detection for feature flag configurations.
7
+ #
8
+ # This module also contains supporting classes and additional mixins for data system
9
+ # implementations, such as DataAvailability, Update, and protocol-specific mixins.
10
+ #
11
+ # For operations that can fail, use {LaunchDarkly::Result} from util.rb.
12
+ #
13
+ # Application code should not need to implement this directly; it is used internally by the
14
+ # SDK's data system implementations.
15
+ #
16
+ # @private
17
+ #
18
+ module DataSystem
19
+ #
20
+ # Starts the data system.
21
+ #
22
+ # This method will return immediately. The returned event will be set when the system
23
+ # has reached an initial state (either permanently failed, e.g. due to bad auth, or succeeded).
24
+ #
25
+ # If called multiple times, returns the same event as the first call.
26
+ #
27
+ # @return [Concurrent::Event] Event that will be set when initialization is complete
28
+ #
29
+ def start
30
+ raise NotImplementedError, "#{self.class} must implement #start"
31
+ end
32
+
33
+ #
34
+ # Halts the data system. Should be called when the client is closed to stop any long running
35
+ # operations. Makes the data system no longer usable.
36
+ #
37
+ # @return [void]
38
+ #
39
+ def stop
40
+ raise NotImplementedError, "#{self.class} must implement #stop"
41
+ end
42
+
43
+ #
44
+ # Returns an interface for tracking the status of the data source.
45
+ #
46
+ # The data source is the mechanism that the SDK uses to get feature flag configurations, such
47
+ # as a streaming connection (the default) or poll requests.
48
+ #
49
+ # @return [LaunchDarkly::Interfaces::DataSource::StatusProvider]
50
+ #
51
+ def data_source_status_provider
52
+ raise NotImplementedError, "#{self.class} must implement #data_source_status_provider"
53
+ end
54
+
55
+ #
56
+ # Returns an interface for tracking the status of a persistent data store.
57
+ #
58
+ # The provider has methods for checking whether the data store is (as far
59
+ # as the SDK knows) currently operational, tracking changes in this
60
+ # status, and getting cache statistics. These are only relevant for a
61
+ # persistent data store; if you are using an in-memory data store, then
62
+ # this method will return a stub object that provides no information.
63
+ #
64
+ # @return [LaunchDarkly::Interfaces::DataStore::StatusProvider]
65
+ #
66
+ def data_store_status_provider
67
+ raise NotImplementedError, "#{self.class} must implement #data_store_status_provider"
68
+ end
69
+
70
+ #
71
+ # Returns the broadcaster for flag change notifications.
72
+ #
73
+ # Consumers can use this broadcaster to build their own flag tracker
74
+ # or listen for flag changes directly.
75
+ #
76
+ # @return [LaunchDarkly::Impl::Broadcaster]
77
+ #
78
+ def flag_change_broadcaster
79
+ raise NotImplementedError, "#{self.class} must implement #flag_change_broadcaster"
80
+ end
81
+
82
+ #
83
+ # Indicates what form of data is currently available.
84
+ #
85
+ # This is calculated dynamically based on current system state.
86
+ #
87
+ # @return [Symbol] one of the {DataAvailability} constants
88
+ #
89
+ def data_availability
90
+ raise NotImplementedError, "#{self.class} must implement #data_availability"
91
+ end
92
+
93
+ #
94
+ # Indicates the ideal form of data attainable given the current configuration.
95
+ #
96
+ # @return [Symbol] one of the {#DataAvailability} constants
97
+ #
98
+ def target_availability
99
+ raise NotImplementedError, "#{self.class} must implement #target_availability"
100
+ end
101
+
102
+ #
103
+ # Returns the data store used by the data system.
104
+ #
105
+ # @return [Object] The read-only store
106
+ #
107
+ def store
108
+ raise NotImplementedError, "#{self.class} must implement #store"
109
+ end
110
+
111
+ #
112
+ # Sets the diagnostic accumulator for streaming initialization metrics.
113
+ # This should be called before start() to ensure metrics are collected.
114
+ #
115
+ # @param diagnostic_accumulator [DiagnosticAccumulator] The diagnostic accumulator
116
+ # @return [void]
117
+ #
118
+ def set_diagnostic_accumulator(diagnostic_accumulator)
119
+ raise NotImplementedError, "#{self.class} must implement #set_diagnostic_accumulator"
120
+ end
121
+
122
+ #
123
+ # Represents the availability of data in the SDK.
124
+ #
125
+ class DataAvailability
126
+ # The SDK has no data and will evaluate flags using the application-provided default values.
127
+ DEFAULTS = :defaults
128
+
129
+ # The SDK has data, not necessarily the latest, which will be used to evaluate flags.
130
+ CACHED = :cached
131
+
132
+ # The SDK has obtained, at least once, the latest known data from LaunchDarkly.
133
+ REFRESHED = :refreshed
134
+
135
+ ALL = [DEFAULTS, CACHED, REFRESHED].freeze
136
+
137
+ #
138
+ # Returns whether this availability level is **at least** as good as the other.
139
+ #
140
+ # @param [Symbol] self_level The current availability level
141
+ # @param [Symbol] other The other availability level to compare against
142
+ # @return [Boolean] true if this availability level is at least as good as the other
143
+ #
144
+ def self.at_least?(self_level, other)
145
+ return true if self_level == other
146
+ return true if self_level == REFRESHED
147
+ return true if self_level == CACHED && other == DEFAULTS
148
+
149
+ false
150
+ end
151
+ end
152
+
153
+ #
154
+ # Mixin that defines the required methods of a diagnostic accumulator implementation.
155
+ # The diagnostic accumulator is used for collecting and reporting diagnostic events
156
+ # to LaunchDarkly for monitoring SDK performance and behavior.
157
+ #
158
+ # Application code should not need to implement this directly; it is used internally by the SDK.
159
+ #
160
+ module DiagnosticAccumulator
161
+ #
162
+ # Record a stream initialization.
163
+ #
164
+ # @param timestamp [Float] The timestamp
165
+ # @param duration [Float] The duration
166
+ # @param failed [Boolean] Whether it failed
167
+ # @return [void]
168
+ #
169
+ def record_stream_init(timestamp, duration, failed)
170
+ raise NotImplementedError, "#{self.class} must implement #record_stream_init"
171
+ end
172
+
173
+ #
174
+ # Record events in a batch.
175
+ #
176
+ # @param events_in_batch [Integer] The number of events
177
+ # @return [void]
178
+ #
179
+ def record_events_in_batch(events_in_batch)
180
+ raise NotImplementedError, "#{self.class} must implement #record_events_in_batch"
181
+ end
182
+
183
+ #
184
+ # Create an event and reset the accumulator.
185
+ #
186
+ # @param dropped_events [Integer] The number of dropped events
187
+ # @param deduplicated_users [Integer] The number of deduplicated users
188
+ # @return [Object] The diagnostic event
189
+ #
190
+ def create_event_and_reset(dropped_events, deduplicated_users)
191
+ raise NotImplementedError, "#{self.class} must implement #create_event_and_reset"
192
+ end
193
+ end
194
+
195
+ #
196
+ # Mixin that defines the required methods for components that can receive a diagnostic accumulator.
197
+ # Components that include this mixin can report diagnostic information to LaunchDarkly for
198
+ # monitoring SDK performance and behavior.
199
+ #
200
+ # Application code should not need to implement this directly; it is used internally by the SDK.
201
+ #
202
+ module DiagnosticSource
203
+ #
204
+ # Set the diagnostic_accumulator to be used for reporting diagnostic events.
205
+ #
206
+ # @param diagnostic_accumulator [DiagnosticAccumulator] The accumulator
207
+ # @return [void]
208
+ #
209
+ def set_diagnostic_accumulator(diagnostic_accumulator)
210
+ raise NotImplementedError, "#{self.class} must implement #set_diagnostic_accumulator"
211
+ end
212
+ end
213
+
214
+ #
215
+ # Mixin that defines the required methods of an initializer implementation. An initializer
216
+ # is a component capable of retrieving a single data result, such as from the LaunchDarkly
217
+ # polling API.
218
+ #
219
+ # The intent of initializers is to quickly fetch an initial set of data, which may be stale
220
+ # but is fast to retrieve. This initial data serves as a foundation for a Synchronizer to
221
+ # build upon, enabling it to provide updates as new changes occur.
222
+ #
223
+ # Application code should not need to implement this directly; it is used internally by the SDK.
224
+ #
225
+ module Initializer
226
+ #
227
+ # Fetch should retrieve the initial data set for the data source, returning
228
+ # a Basis object on success, or an error message on failure.
229
+ #
230
+ # @return [LaunchDarkly::Result] A Result containing either a Basis or an error message
231
+ #
232
+ def fetch
233
+ raise NotImplementedError, "#{self.class} must implement #fetch"
234
+ end
235
+ end
236
+
237
+ #
238
+ # Update represents the results of a synchronizer's ongoing sync method.
239
+ #
240
+ class Update
241
+ # @return [Symbol] The state of the data source
242
+ attr_reader :state
243
+
244
+ # @return [ChangeSet, nil] The change set if available
245
+ attr_reader :change_set
246
+
247
+ # @return [LaunchDarkly::Interfaces::DataSource::ErrorInfo, nil] Error information if applicable
248
+ attr_reader :error
249
+
250
+ # @return [Boolean] Whether to revert to FDv1
251
+ attr_reader :revert_to_fdv1
252
+
253
+ # @return [String, nil] The environment ID if available
254
+ attr_reader :environment_id
255
+
256
+ #
257
+ # @param state [Symbol] The state of the data source
258
+ # @param change_set [ChangeSet, nil] The change set if available
259
+ # @param error [LaunchDarkly::Interfaces::DataSource::ErrorInfo, nil] Error information if applicable
260
+ # @param revert_to_fdv1 [Boolean] Whether to revert to FDv1
261
+ # @param environment_id [String, nil] The environment ID if available
262
+ #
263
+ def initialize(state:, change_set: nil, error: nil, revert_to_fdv1: false, environment_id: nil)
264
+ @state = state
265
+ @change_set = change_set
266
+ @error = error
267
+ @revert_to_fdv1 = revert_to_fdv1
268
+ @environment_id = environment_id
269
+ end
270
+ end
271
+
272
+ #
273
+ # Mixin that defines the required methods of a synchronizer implementation. A synchronizer
274
+ # is a component capable of synchronizing data from an external data source, such as a
275
+ # streaming or polling API.
276
+ #
277
+ # It is responsible for yielding Update objects that represent the current state of the
278
+ # data source, including any changes that have occurred since the last synchronization.
279
+ #
280
+ # Application code should not need to implement this directly; it is used internally by the SDK.
281
+ #
282
+ module Synchronizer
283
+ #
284
+ # Sync should begin the synchronization process for the data source, yielding
285
+ # Update objects until the connection is closed or an unrecoverable error
286
+ # occurs.
287
+ #
288
+ # @yield [Update] Yields Update objects as synchronization progresses
289
+ # @return [void]
290
+ #
291
+ def sync
292
+ raise NotImplementedError, "#{self.class} must implement #sync"
293
+ end
294
+ end
295
+ end
296
+ end
297
+ end
298
+
@@ -102,7 +102,7 @@ module LaunchDarkly
102
102
  @last_version += 1
103
103
  }
104
104
 
105
- parsed = parse_content(IO.read(path))
105
+ parsed = parse_content(File.read(path))
106
106
  (parsed[:flags] || {}).each do |key, flag|
107
107
  flag[:version] = version
108
108
  add_item(all_data, FEATURES, flag)
@@ -5,7 +5,6 @@ module LaunchDarkly
5
5
  module Impl
6
6
  module Integrations
7
7
  module TestData
8
- # @private
9
8
  class TestDataSource
10
9
  include LaunchDarkly::Interfaces::DataSource
11
10
 
@@ -2,6 +2,7 @@ require "ldclient-rb/impl/big_segments"
2
2
  require "ldclient-rb/impl/broadcaster"
3
3
  require "ldclient-rb/impl/data_source"
4
4
  require "ldclient-rb/impl/data_store"
5
+ require "ldclient-rb/impl/data_source/null_processor"
5
6
  require "ldclient-rb/impl/diagnostic_events"
6
7
  require "ldclient-rb/impl/evaluator"
7
8
  require "ldclient-rb/impl/evaluation_with_hook_result"
@@ -132,7 +133,7 @@ module LaunchDarkly
132
133
 
133
134
  if @config.use_ldd?
134
135
  @config.logger.info { "[LDClient] Started LaunchDarkly Client in LDD mode" }
135
- @data_source = NullUpdateProcessor.new
136
+ @data_source = LaunchDarkly::Impl::DataSource::NullUpdateProcessor.new
136
137
  return # requestor and update processor are not used in this mode
137
138
  end
138
139
 
@@ -710,7 +711,7 @@ module LaunchDarkly
710
711
 
711
712
  def create_default_data_source(sdk_key, config, diagnostic_accumulator)
712
713
  if config.offline?
713
- return NullUpdateProcessor.new
714
+ return LaunchDarkly::Impl::DataSource::NullUpdateProcessor.new
714
715
  end
715
716
  raise ArgumentError, "sdk_key must not be nil" if sdk_key.nil? # see LDClient constructor comment on sdk_key
716
717
  if config.stream?
@@ -877,23 +878,4 @@ module LaunchDarkly
877
878
  false
878
879
  end
879
880
  end
880
-
881
- #
882
- # Used internally when the client is offline.
883
- # @private
884
- #
885
- class NullUpdateProcessor
886
- def start
887
- e = Concurrent::Event.new
888
- e.set
889
- e
890
- end
891
-
892
- def initialized?
893
- true
894
- end
895
-
896
- def stop
897
- end
898
- end
899
881
  end
@@ -25,6 +25,7 @@ module LaunchDarkly
25
25
  def initialize(sdk_key, config, diagnostic_accumulator = nil)
26
26
  @sdk_key = sdk_key
27
27
  @config = config
28
+ @diagnostic_accumulator = diagnostic_accumulator
28
29
  @data_source_update_sink = config.data_source_update_sink
29
30
  @feature_store = config.feature_store
30
31
  @initialized = Concurrent::AtomicBoolean.new(false)
@@ -1,3 +1,3 @@
1
1
  module LaunchDarkly
2
- VERSION = "8.11.1" # x-release-please-version
2
+ VERSION = "8.11.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.11.1
4
+ version: 8.11.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - LaunchDarkly
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-10 00:00:00.000000000 Z
11
+ date: 2025-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-dynamodb
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.57'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bigdecimal
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.1.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 3.1.1
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -386,7 +400,10 @@ files:
386
400
  - lib/ldclient-rb/impl/context.rb
387
401
  - lib/ldclient-rb/impl/context_filter.rb
388
402
  - lib/ldclient-rb/impl/data_source.rb
403
+ - lib/ldclient-rb/impl/data_source/null_processor.rb
389
404
  - lib/ldclient-rb/impl/data_store.rb
405
+ - lib/ldclient-rb/impl/data_system.rb
406
+ - lib/ldclient-rb/impl/data_system/fdv1.rb
390
407
  - lib/ldclient-rb/impl/dependency_tracker.rb
391
408
  - lib/ldclient-rb/impl/diagnostic_events.rb
392
409
  - lib/ldclient-rb/impl/evaluation_with_hook_result.rb