launchdarkly-server-sdk 8.13.0-java → 8.14.0-java

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: 94c8797b35ad5d1abce1827cd6eaf48961856cf8102eabe2d9de1c674c17405a
4
- data.tar.gz: 7f02d923d1522f3976ee5ab457379dd5f40992539894175ce93a54083d107bca
3
+ metadata.gz: c6f092405b663bdca252bd2f617e1c81b8000860c5a711c6cfb3d0214f7d366d
4
+ data.tar.gz: 5915a81dd336f244663cda3c52a68329a1d35c3b71716b5a050929df685ea5aa
5
5
  SHA512:
6
- metadata.gz: 7fde3a50440b01752b84cebe45fbcb660258252ba1d162fbfc20fb5131686751de4c917ce1e61441d0981b606f4a44091a4724792019476bf27dd852a68877b6
7
- data.tar.gz: f1efa40715fb7909b2793d89de9e4f957f8ac468c5865c4fa46a0b111c0544cb627fc9ec0c0c477ea6718eac2ff18decd0d3d54b0c7edcacf7168c23d8f2343c
6
+ metadata.gz: 03b8f0e3c245e462e7de04adb9c9ea9a63d4f6c61eeb6564a7a668235c7a565aac296233a28079fefeff199b8b5dcb78baff34098180a7fd7c7d2fdb7ddf3c1c
7
+ data.tar.gz: 19e70edd5df9b330aa1a68e0faa6ab4453bb7772629fad7b3b79271fb41b7003028a84b4719c2250987cf2db41d31f3c39fdc94ef3459d10c3f622aa32ba2f94
data/README.md CHANGED
@@ -43,7 +43,7 @@ We encourage pull requests and other contributions from the community. Check out
43
43
  Verifying SDK build provenance with the SLSA framework
44
44
  ------------
45
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).
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
47
 
48
48
  About LaunchDarkly
49
49
  -----------
@@ -697,9 +697,6 @@ module LaunchDarkly
697
697
  #
698
698
  # Configuration for LaunchDarkly's data acquisition strategy.
699
699
  #
700
- # This is not stable and is not subject to any backwards compatibility guarantees
701
- # or semantic versioning. It is not suitable for production usage.
702
- #
703
700
  class DataSystemConfig
704
701
  #
705
702
  # @param initializers [Array<#build(String, Config)>, nil] The (optional) array of builders
@@ -21,9 +21,9 @@ module LaunchDarkly
21
21
  # include LaunchDarkly::DataSystem::Requester
22
22
  #
23
23
  # def fetch(selector)
24
- # # Fetch data and return a Result containing [ChangeSet, headers]
25
- # # ...
26
- # LaunchDarkly::Result.success([change_set, {}])
24
+ # # Fetch data and return a Result whose value is a ChangeSet and
25
+ # # whose headers carry any response metadata (e.g. directives).
26
+ # LaunchDarkly::Result.success(change_set, response_headers)
27
27
  # end
28
28
  #
29
29
  # def stop
@@ -43,8 +43,10 @@ module LaunchDarkly
43
43
  # @param selector [LaunchDarkly::Interfaces::DataSystem::Selector, nil]
44
44
  # The selector describing what data to fetch. May be nil if no
45
45
  # selector is available (e.g., on the first request).
46
- # @return [LaunchDarkly::Result] A Result containing a tuple of
47
- # [ChangeSet, headers] on success, or an error message on failure.
46
+ # @return [LaunchDarkly::Result] A Result whose `value` is a
47
+ # {LaunchDarkly::Interfaces::DataSystem::ChangeSet} on success and
48
+ # whose `headers` carry response headers in either case (so callers
49
+ # can inspect directives such as `X-LD-FD-Fallback`).
48
50
  #
49
51
  def fetch(selector)
50
52
  raise NotImplementedError
@@ -65,6 +65,18 @@ module LaunchDarkly
65
65
  @store.initialized?
66
66
  end
67
67
 
68
+ #
69
+ # Passthrough for the FDv2 store coordinator. If the wrapped store supports
70
+ # disabling its cache (e.g. {LaunchDarkly::Integrations::Util::CachingStoreWrapper}),
71
+ # forward the call; otherwise no-op.
72
+ #
73
+ # @return [void]
74
+ #
75
+ def disable_cache
76
+ return unless @store.respond_to?(:disable_cache)
77
+ wrapper { @store.disable_cache }
78
+ end
79
+
68
80
  # (see LaunchDarkly::Interfaces::FeatureStore#stop)
69
81
  def stop
70
82
  poller_to_stop = nil
@@ -221,6 +221,12 @@ module LaunchDarkly
221
221
  # Switch to memory store as active
222
222
  @active_store = @memory_store
223
223
 
224
+ # In-memory store is now authoritative. Disable the persistent-store cache
225
+ # so we don't hold a duplicate copy of every flag. Done before the
226
+ # persistent_store.init below so the wrapper can skip its cache-population
227
+ # loop on this very call.
228
+ disable_persistent_cache
229
+
224
230
  # Persist to persistent store if configured and writable
225
231
  @persistent_store.init(collections) if should_persist?
226
232
 
@@ -271,6 +277,24 @@ module LaunchDarkly
271
277
  send_change_events(affected_items) unless affected_items.empty?
272
278
  end
273
279
 
280
+ #
281
+ # Disable the persistent store's in-memory cache, if it has one. The FDv2 in-memory
282
+ # store is now the source of truth, so the cache is dead weight and would just
283
+ # hold a duplicate copy of every flag.
284
+ #
285
+ # @return [void]
286
+ #
287
+ private def disable_persistent_cache
288
+ return if @persistent_store.nil?
289
+ return unless @persistent_store.respond_to?(:disable_cache)
290
+
291
+ begin
292
+ @persistent_store.disable_cache
293
+ rescue => e
294
+ @logger.warn { "[LDClient] Failed to disable persistent store cache: #{e.message}" }
295
+ end
296
+ end
297
+
274
298
  #
275
299
  # Returns whether data should be persisted to the persistent store.
276
300
  #
@@ -214,8 +214,23 @@ module LaunchDarkly
214
214
  nil
215
215
  )
216
216
 
217
- # Run initializers first
218
- run_initializers
217
+ # Run initializers first. If an initializer signals the
218
+ # server-directed FDv1 Fallback Directive, switch terminally to
219
+ # the FDv1 Fallback Synchronizer (or transition to OFF if none
220
+ # is configured) before entering the synchronizer phase.
221
+ if run_initializers
222
+ if @fdv1_fallback_synchronizer_builder
223
+ @logger.warn { "[LDClient] Falling back to FDv1 protocol" }
224
+ @synchronizer_builders = [@fdv1_fallback_synchronizer_builder]
225
+ else
226
+ @logger.warn { "[LDClient] Initializer requested FDv1 fallback but none configured" }
227
+ @synchronizer_builders = []
228
+ @data_source_status_provider.update_status(
229
+ LaunchDarkly::Interfaces::DataSource::Status::OFF,
230
+ @data_source_status_provider.status.last_error
231
+ )
232
+ end
233
+ end
219
234
 
220
235
  # Run synchronizers
221
236
  run_synchronizers
@@ -228,39 +243,70 @@ module LaunchDarkly
228
243
  #
229
244
  # Run initializers to get initial data.
230
245
  #
231
- # @return [void]
246
+ # Each initializer is tried in order until one succeeds, the system
247
+ # is stopped, or an initializer signals the server-directed FDv1
248
+ # Fallback Directive. When fallback is signalled alongside a valid
249
+ # payload, that payload is applied before returning so evaluations
250
+ # can serve the server-provided data while the FDv1 synchronizer
251
+ # spins up. The method returns true when fallback was requested so
252
+ # that the caller can switch the synchronizer list.
253
+ #
254
+ # @return [Boolean] true when an initializer requested FDv1 fallback.
232
255
  #
233
256
  def run_initializers
234
- return unless @data_system_config.initializers
257
+ return false unless @data_system_config.initializers
235
258
 
236
259
  @data_system_config.initializers.each do |initializer_builder|
237
- return if @stop_event.set?
260
+ return false if @stop_event.set?
238
261
 
239
262
  begin
240
263
  initializer = initializer_builder.build(@sdk_key, @config)
241
264
  @logger.info { "[LDClient] Attempting to initialize via #{initializer.name}" }
242
265
 
243
- basis_result = initializer.fetch(@store)
266
+ fetch_result = initializer.fetch(@store)
267
+ fallback = fetch_result.fallback_to_fdv1
268
+ basis_result = fetch_result.result
244
269
 
245
270
  if basis_result.success?
246
271
  basis = basis_result.value
247
272
  @logger.info { "[LDClient] Initialized via #{initializer.name}" }
248
273
 
249
- # Apply the basis to the store
274
+ # Apply the basis to the store regardless of whether fallback was signalled.
275
+ # If the server returned a valid payload alongside the directive we still want
276
+ # evaluations to serve that data while the FDv1 synchronizer spins up.
250
277
  @store.apply(basis.change_set, basis.persist)
251
278
 
252
- # Set ready event if and only if a selector is defined for the changeset
279
+ # Set ready event if and only if a selector is defined for the changeset.
253
280
  if basis.change_set.selector && basis.change_set.selector.defined?
254
281
  @ready_event.set
255
- return
282
+ return fallback
256
283
  end
257
284
  else
258
285
  @logger.warn { "[LDClient] Initializer #{initializer.name} failed: #{basis_result.error}" }
286
+ if fallback
287
+ # Record the underlying initializer error so that, if no FDv1 fallback is
288
+ # configured, the subsequent transition to OFF carries it as last_error.
289
+ @data_source_status_provider.update_status(
290
+ LaunchDarkly::Interfaces::DataSource::Status::INITIALIZING,
291
+ LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(
292
+ LaunchDarkly::Interfaces::DataSource::ErrorInfo::UNKNOWN,
293
+ 0,
294
+ basis_result.error || "",
295
+ Time.now
296
+ )
297
+ )
298
+ end
259
299
  end
300
+
301
+ # The fallback directive takes precedence over the regular failover algorithm,
302
+ # so do not fall through to the next initializer when it is set.
303
+ return true if fallback
260
304
  rescue => e
261
305
  @logger.error { "[LDClient] Initializer failed with exception: #{e.message}" }
262
306
  end
263
307
  end
308
+
309
+ false
264
310
  end
265
311
 
266
312
  #
@@ -313,12 +359,21 @@ module LaunchDarkly
313
359
  case sync_result
314
360
  when SyncResult::FDV1
315
361
  if @fdv1_fallback_synchronizer_builder
362
+ @logger.warn { "[LDClient] Falling back to FDv1 protocol" }
316
363
  @synchronizer_builders = [@fdv1_fallback_synchronizer_builder]
317
364
  current_index = 0
318
365
  next
319
366
  end
320
- # No FDv1 fallback configured, treat as regular fallback
321
- current_index += 1
367
+ # No FDv1 fallback configured: the data system must HALT
368
+ # rather than fall through to the next FDv2 synchronizer.
369
+ # Continuing to retry would reopen the connection that just
370
+ # delivered the directive.
371
+ @logger.warn { "[LDClient] Synchronizer requested FDv1 fallback but none configured; halting data system" }
372
+ @data_source_status_provider.update_status(
373
+ LaunchDarkly::Interfaces::DataSource::Status::OFF,
374
+ @data_source_status_provider.status.last_error
375
+ )
376
+ break
322
377
  when SyncResult::RECOVER
323
378
  @logger.info { "[LDClient] Recovery condition met, returning to primary synchronizer" }
324
379
  current_index = 0
@@ -410,7 +465,7 @@ module LaunchDarkly
410
465
  # Update status
411
466
  @data_source_status_provider.update_status(update.state, update.error)
412
467
 
413
- return SyncResult::FDV1 if update.revert_to_fdv1
468
+ return SyncResult::FDV1 if update.fallback_to_fdv1
414
469
 
415
470
  return SyncResult::REMOVE if update.state == LaunchDarkly::Interfaces::DataSource::Status::OFF
416
471
  end
@@ -21,6 +21,60 @@ module LaunchDarkly
21
21
  LD_ENVID_HEADER = "X-LD-EnvID"
22
22
  LD_FD_FALLBACK_HEADER = "X-LD-FD-Fallback"
23
23
 
24
+ #
25
+ # Reports whether the response headers signal that the SDK should fall
26
+ # back to the FDv1 protocol. Lookup is case-insensitive so callers do
27
+ # not need to know whether the header map preserves canonical casing
28
+ # (e.g. {HTTP::Headers}) or has been normalized to lowercase (e.g.
29
+ # {HTTPPollingRequester#fetch}).
30
+ #
31
+ # @param headers [#[], Hash, nil]
32
+ # @return [Boolean]
33
+ #
34
+ def self.fdv1_fallback_requested?(headers)
35
+ return false if headers.nil?
36
+ value = lookup_header(headers, LD_FD_FALLBACK_HEADER)
37
+ # http gem returns arrays for repeated headers; normalize to a string.
38
+ value = value.first if value.is_a?(Array)
39
+ value == 'true'
40
+ end
41
+
42
+ #
43
+ # Performs a case-insensitive header lookup that works with both
44
+ # case-insensitive header containers (e.g. `HTTP::Headers`) and plain
45
+ # Ruby hashes -- including hashes whose keys we have downcased
46
+ # ourselves before reaching this code path.
47
+ #
48
+ # @param headers [#[], Hash]
49
+ # @param name [String]
50
+ # @return [String, Array, nil]
51
+ #
52
+ def self.lookup_header(headers, name)
53
+ return nil if headers.nil?
54
+
55
+ if headers.is_a?(Hash)
56
+ # Plain hash: try canonical case, then exact lowercase, then a
57
+ # case-insensitive scan as a final fallback.
58
+ value = headers[name]
59
+ return value unless value.nil?
60
+
61
+ downcased = name.downcase
62
+ value = headers[downcased]
63
+ return value unless value.nil?
64
+
65
+ headers.each_pair do |key, val|
66
+ return val if key.to_s.downcase == downcased
67
+ end
68
+ return nil
69
+ end
70
+
71
+ # Non-hash container (e.g. HTTP::Headers). Lookup via [] is
72
+ # already case-insensitive on those types.
73
+ return headers[name] if headers.respond_to?(:[])
74
+
75
+ nil
76
+ end
77
+
24
78
  #
25
79
  # PollingDataSource is a data source that can retrieve information from
26
80
  # LaunchDarkly either as an Initializer or as a Synchronizer.
@@ -46,10 +100,12 @@ module LaunchDarkly
46
100
  end
47
101
 
48
102
  #
49
- # Fetch returns a Basis, or an error if the Basis could not be retrieved.
103
+ # Fetch returns a {LaunchDarkly::Interfaces::DataSystem::FetchResult}
104
+ # wrapping a Basis (or an error) and the FDv1 Fallback Directive
105
+ # signal carried on the server response.
50
106
  #
51
107
  # @param ss [LaunchDarkly::Interfaces::DataSystem::SelectorStore]
52
- # @return [LaunchDarkly::Interfaces::DataSystem::Basis, nil]
108
+ # @return [LaunchDarkly::Interfaces::DataSystem::FetchResult]
53
109
  #
54
110
  def fetch(ss)
55
111
  poll(ss)
@@ -71,16 +127,10 @@ module LaunchDarkly
71
127
 
72
128
  until @stop.set?
73
129
  result = @requester.fetch(ss.selector)
130
+ fallback = LaunchDarkly::Impl::DataSystem.fdv1_fallback_requested?(result.headers)
131
+ envid = LaunchDarkly::Impl::DataSystem.lookup_header(result.headers, LD_ENVID_HEADER)
74
132
 
75
133
  if !result.success?
76
- fallback = false
77
- envid = nil
78
-
79
- if result.headers
80
- fallback = result.headers[LD_FD_FALLBACK_HEADER] == 'true'
81
- envid = result.headers[LD_ENVID_HEADER]
82
- end
83
-
84
134
  if result.exception.is_a?(LaunchDarkly::Impl::DataSource::UnexpectedResponseError)
85
135
  error_info = LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(
86
136
  LaunchDarkly::Interfaces::DataSource::ErrorInfo::ERROR_RESPONSE,
@@ -99,7 +149,7 @@ module LaunchDarkly
99
149
  state: LaunchDarkly::Interfaces::DataSource::Status::OFF,
100
150
  error: error_info,
101
151
  environment_id: envid,
102
- revert_to_fdv1: true
152
+ fallback_to_fdv1: true
103
153
  )
104
154
  break
105
155
  end
@@ -108,7 +158,7 @@ module LaunchDarkly
108
158
  state: LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED,
109
159
  error: error_info,
110
160
  environment_id: envid,
111
- revert_to_fdv1: false
161
+ fallback_to_fdv1: false
112
162
  )
113
163
  @interrupt_event.wait(@poll_interval)
114
164
  next
@@ -118,7 +168,7 @@ module LaunchDarkly
118
168
  state: LaunchDarkly::Interfaces::DataSource::Status::OFF,
119
169
  error: error_info,
120
170
  environment_id: envid,
121
- revert_to_fdv1: fallback
171
+ fallback_to_fdv1: fallback
122
172
  )
123
173
  break
124
174
  end
@@ -136,7 +186,7 @@ module LaunchDarkly
136
186
  state: LaunchDarkly::Interfaces::DataSource::Status::OFF,
137
187
  error: error_info,
138
188
  environment_id: envid,
139
- revert_to_fdv1: true
189
+ fallback_to_fdv1: true
140
190
  )
141
191
  break
142
192
  end
@@ -145,16 +195,14 @@ module LaunchDarkly
145
195
  state: LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED,
146
196
  error: error_info,
147
197
  environment_id: envid,
148
- revert_to_fdv1: false
198
+ fallback_to_fdv1: false
149
199
  )
150
200
  else
151
- change_set, headers = result.value
152
- fallback = headers[LD_FD_FALLBACK_HEADER] == 'true'
153
201
  yield LaunchDarkly::Interfaces::DataSystem::Update.new(
154
202
  state: LaunchDarkly::Interfaces::DataSource::Status::VALID,
155
- change_set: change_set,
156
- environment_id: headers[LD_ENVID_HEADER],
157
- revert_to_fdv1: fallback
203
+ change_set: result.value,
204
+ environment_id: envid,
205
+ fallback_to_fdv1: fallback
158
206
  )
159
207
  end
160
208
 
@@ -177,10 +225,14 @@ module LaunchDarkly
177
225
 
178
226
  #
179
227
  # @param ss [LaunchDarkly::Interfaces::DataSystem::SelectorStore]
180
- # @return [LaunchDarkly::Result<LaunchDarkly::Interfaces::DataSystem::Basis, String>]
228
+ # @return [LaunchDarkly::Interfaces::DataSystem::FetchResult]
181
229
  #
182
230
  private def poll(ss)
231
+ # Default to false so the rescue clause has a defined value even when an
232
+ # exception is raised before the header read below has had a chance to run.
233
+ fallback = false
183
234
  result = @requester.fetch(ss.selector)
235
+ fallback = LaunchDarkly::Impl::DataSystem.fdv1_fallback_requested?(result.headers)
184
236
 
185
237
  unless result.success?
186
238
  if result.exception.is_a?(LaunchDarkly::Impl::DataSource::UnexpectedResponseError)
@@ -189,15 +241,20 @@ module LaunchDarkly
189
241
  status_code, "polling request", "will retry"
190
242
  )
191
243
  @logger.warn { "[LDClient] #{http_error_message_result}" } if Impl::Util.http_error_recoverable?(status_code)
192
- return LaunchDarkly::Result.fail(http_error_message_result, result.exception)
244
+ return LaunchDarkly::Interfaces::DataSystem::FetchResult.new(
245
+ result: LaunchDarkly::Result.fail(http_error_message_result, result.exception),
246
+ fallback_to_fdv1: fallback
247
+ )
193
248
  end
194
249
 
195
- return LaunchDarkly::Result.fail(result.error || 'Failed to request payload', result.exception)
250
+ return LaunchDarkly::Interfaces::DataSystem::FetchResult.new(
251
+ result: LaunchDarkly::Result.fail(result.error || 'Failed to request payload', result.exception),
252
+ fallback_to_fdv1: fallback
253
+ )
196
254
  end
197
255
 
198
- change_set, headers = result.value
199
-
200
- env_id = headers[LD_ENVID_HEADER]
256
+ change_set = result.value
257
+ env_id = LaunchDarkly::Impl::DataSystem.lookup_header(result.headers, LD_ENVID_HEADER)
201
258
  env_id = nil unless env_id.is_a?(String)
202
259
 
203
260
  basis = LaunchDarkly::Interfaces::DataSystem::Basis.new(
@@ -206,12 +263,22 @@ module LaunchDarkly
206
263
  environment_id: env_id
207
264
  )
208
265
 
209
- LaunchDarkly::Result.success(basis)
266
+ LaunchDarkly::Interfaces::DataSystem::FetchResult.new(
267
+ result: LaunchDarkly::Result.success(basis),
268
+ fallback_to_fdv1: fallback
269
+ )
210
270
  rescue => e
271
+ # An exception can fire after we have already read the response
272
+ # headers (e.g. a malformed change_set whose selector is nil makes
273
+ # change_set.selector.defined? raise). Carry the computed fallback
274
+ # signal through so the directive is not silently dropped.
211
275
  msg = "Error: Exception encountered when updating flags. #{e}"
212
276
  @logger.error { "[LDClient] #{msg}" }
213
277
  @logger.debug { "[LDClient] Exception trace: #{e.backtrace}" }
214
- LaunchDarkly::Result.fail(msg, e)
278
+ LaunchDarkly::Interfaces::DataSystem::FetchResult.new(
279
+ result: LaunchDarkly::Result.fail(msg, e),
280
+ fallback_to_fdv1: fallback
281
+ )
215
282
  end
216
283
  end
217
284
 
@@ -273,7 +340,7 @@ module LaunchDarkly
273
340
  end
274
341
 
275
342
  if status == 304
276
- return LaunchDarkly::Result.success([LaunchDarkly::Interfaces::DataSystem::ChangeSetBuilder.no_changes, response_headers])
343
+ return LaunchDarkly::Result.success(LaunchDarkly::Interfaces::DataSystem::ChangeSetBuilder.no_changes, response_headers)
277
344
  end
278
345
 
279
346
  body = response.to_s
@@ -285,7 +352,7 @@ module LaunchDarkly
285
352
 
286
353
  changeset_result = LaunchDarkly::Impl::DataSystem.polling_payload_to_changeset(data)
287
354
  if changeset_result.success?
288
- LaunchDarkly::Result.success([changeset_result.value, response_headers])
355
+ LaunchDarkly::Result.success(changeset_result.value, response_headers)
289
356
  else
290
357
  LaunchDarkly::Result.fail(changeset_result.error, changeset_result.exception, response_headers)
291
358
  end
@@ -361,7 +428,7 @@ module LaunchDarkly
361
428
  end
362
429
 
363
430
  if status == 304
364
- return LaunchDarkly::Result.success([LaunchDarkly::Interfaces::DataSystem::ChangeSetBuilder.no_changes, response_headers])
431
+ return LaunchDarkly::Result.success(LaunchDarkly::Interfaces::DataSystem::ChangeSetBuilder.no_changes, response_headers)
365
432
  end
366
433
 
367
434
  body = response.to_s
@@ -373,7 +440,7 @@ module LaunchDarkly
373
440
 
374
441
  changeset_result = LaunchDarkly::Impl::DataSystem.fdv1_polling_payload_to_changeset(data)
375
442
  if changeset_result.success?
376
- LaunchDarkly::Result.success([changeset_result.value, response_headers])
443
+ LaunchDarkly::Result.success(changeset_result.value, response_headers)
377
444
  else
378
445
  LaunchDarkly::Result.fail(changeset_result.error, changeset_result.exception, response_headers)
379
446
  end
@@ -12,9 +12,6 @@ module LaunchDarkly
12
12
  #
13
13
  # DeleteObject specifies the deletion of a particular object.
14
14
  #
15
- # This type is not stable, and not subject to any backwards
16
- # compatibility guarantees or semantic versioning. It is not suitable for production usage.
17
- #
18
15
  class DeleteObject
19
16
  # @return [Integer] The version
20
17
  attr_reader :version
@@ -79,9 +76,6 @@ module LaunchDarkly
79
76
  #
80
77
  # PutObject specifies the addition of a particular object with upsert semantics.
81
78
  #
82
- # This type is not stable, and not subject to any backwards
83
- # compatibility guarantees or semantic versioning. It is not suitable for production usage.
84
- #
85
79
  class PutObject
86
80
  # @return [Integer] The version
87
81
  attr_reader :version
@@ -153,28 +147,15 @@ module LaunchDarkly
153
147
  #
154
148
  # Goodbye represents a goodbye event.
155
149
  #
156
- # This type is not stable, and not subject to any backwards
157
- # compatibility guarantees or semantic versioning. It is not suitable for production usage.
158
- #
159
150
  class Goodbye
160
151
  # @return [String] The reason for goodbye
161
152
  attr_reader :reason
162
153
 
163
- # @return [Boolean] Whether the goodbye is silent
164
- attr_reader :silent
165
-
166
- # @return [Boolean] Whether this represents a catastrophic failure
167
- attr_reader :catastrophe
168
-
169
154
  #
170
155
  # @param reason [String] The reason for goodbye
171
- # @param silent [Boolean] Whether the goodbye is silent
172
- # @param catastrophe [Boolean] Whether this represents a catastrophic failure
173
156
  #
174
- def initialize(reason:, silent:, catastrophe:)
157
+ def initialize(reason:)
175
158
  @reason = reason
176
- @silent = silent
177
- @catastrophe = catastrophe
178
159
  end
179
160
 
180
161
  #
@@ -185,8 +166,6 @@ module LaunchDarkly
185
166
  def to_h
186
167
  {
187
168
  reason: @reason,
188
- silent: @silent,
189
- catastrophe: @catastrophe,
190
169
  }
191
170
  end
192
171
 
@@ -199,21 +178,16 @@ module LaunchDarkly
199
178
  #
200
179
  def self.from_h(data)
201
180
  reason = data[:reason]
202
- silent = data[:silent]
203
- catastrophe = data[:catastrophe]
204
181
 
205
- raise ArgumentError, "Missing required fields in Goodbye" if reason.nil? || silent.nil? || catastrophe.nil?
182
+ raise ArgumentError, "Missing required fields in Goodbye" if reason.nil?
206
183
 
207
- new(reason: reason, silent: silent, catastrophe: catastrophe)
184
+ new(reason: reason)
208
185
  end
209
186
  end
210
187
 
211
188
  #
212
189
  # Error represents an error event.
213
190
  #
214
- # This type is not stable, and not subject to any backwards
215
- # compatibility guarantees or semantic versioning. It is not suitable for production usage.
216
- #
217
191
  class Error
218
192
  # @return [String] The payload ID
219
193
  attr_reader :payload_id