Module: LaunchDarkly::Impl::DataSystem Private

Included in:
FDv1, FDv2
Defined in:
lib/ldclient-rb/impl/data_system.rb,
lib/ldclient-rb/impl/data_system/fdv1.rb,
lib/ldclient-rb/impl/data_system/fdv2.rb,
lib/ldclient-rb/impl/data_system/polling.rb,
lib/ldclient-rb/impl/data_system/streaming.rb,
lib/ldclient-rb/impl/data_system/protocolv2.rb,
lib/ldclient-rb/impl/data_system/http_config_options.rb,
lib/ldclient-rb/impl/data_system/data_source_builder_common.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Mixin that defines the required methods of a data system implementation. The data system is responsible for managing the SDK’s data model, including storage, retrieval, and change detection for feature flag configurations.

This module also contains supporting classes and additional mixins for data system implementations, such as DataAvailability, Update, and protocol-specific mixins.

For operations that can fail, use Result from util.rb.

Application code should not need to implement this directly; it is used internally by the SDK’s data system implementations.

Since:

  • 5.5.0

API:

  • private

Defined Under Namespace

Modules: DataSourceBuilderCommon, DiagnosticAccumulator, DiagnosticSource, Initializer, ProtocolV2, Requester, SyncResult, Synchronizer Classes: DataAvailability, FDv1, FDv1PollingDataSourceBuilder, FDv2, HTTPFDv1PollingRequester, HTTPPollingRequester, HttpConfigOptions, PollingDataSource, PollingDataSourceBuilder, StreamingDataSource, StreamingDataSourceBuilder, Update

Constant Summary collapse

FDV2_POLLING_ENDPOINT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 5.5.0

API:

  • private

"/sdk/poll"
FDV1_POLLING_ENDPOINT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 5.5.0

API:

  • private

"/sdk/latest-all"
LD_ENVID_HEADER =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 5.5.0

API:

  • private

"X-LD-EnvID"
LD_FD_FALLBACK_HEADER =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 5.5.0

API:

  • private

"X-LD-FD-Fallback"
FDV2_STREAMING_ENDPOINT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 5.5.0

API:

  • private

"/sdk/stream"
STREAM_READ_TIMEOUT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Allows for up to 5 minutes to elapse without any data sent across the stream. The heartbeats sent as comments on the stream will keep this from triggering.

Since:

  • 5.5.0

API:

  • private

5 * 60

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.fdv1_polling_payload_to_changeset(data) ⇒ LaunchDarkly::Result<LaunchDarkly::Interfaces::DataSystem::ChangeSet, String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Converts an FDv1 polling payload into a ChangeSet.

Parameters:

  • The FDv1 polling payload

Returns:

  • Result containing ChangeSet on success, or error message on failure

Since:

  • 5.5.0

API:

  • private



496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
# File 'lib/ldclient-rb/impl/data_system/polling.rb', line 496

def self.fdv1_polling_payload_to_changeset(data)
  builder = LaunchDarkly::Interfaces::DataSystem::ChangeSetBuilder.new
  builder.start(LaunchDarkly::Interfaces::DataSystem::IntentCode::TRANSFER_FULL)
  selector = LaunchDarkly::Interfaces::DataSystem::Selector.no_selector

  kind_mappings = [
    [LaunchDarkly::Interfaces::DataSystem::ObjectKind::FLAG, :flags],
    [LaunchDarkly::Interfaces::DataSystem::ObjectKind::SEGMENT, :segments],
  ]

  kind_mappings.each do |kind, fdv1_key|
    kind_data = data[fdv1_key]
    next if kind_data.nil?

    unless kind_data.is_a?(Hash)
      return LaunchDarkly::Result.fail("Invalid format: #{fdv1_key} is not an object")
    end

    kind_data.each do |key, flag_or_segment|
      unless flag_or_segment.is_a?(Hash)
        return LaunchDarkly::Result.fail("Invalid format: #{key} is not an object")
      end

      version = flag_or_segment[:version]
      return LaunchDarkly::Result.fail("Invalid format: #{key} does not have a version set") if version.nil?

      builder.add_put(kind, key, version, flag_or_segment)
    end
  end

  LaunchDarkly::Result.success(builder.finish(selector))
end

.polling_payload_to_changeset(data) ⇒ LaunchDarkly::Result<LaunchDarkly::Interfaces::DataSystem::ChangeSet, String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Converts a polling payload into a ChangeSet.

Parameters:

  • The polling payload

Returns:

  • Result containing ChangeSet on success, or error message on failure

Since:

  • 5.5.0

API:

  • private



430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# File 'lib/ldclient-rb/impl/data_system/polling.rb', line 430

def self.polling_payload_to_changeset(data)
  unless data[:events].is_a?(Array)
    return LaunchDarkly::Result.fail("Invalid payload: 'events' key is missing or not a list")
  end

  builder = LaunchDarkly::Interfaces::DataSystem::ChangeSetBuilder.new

  data[:events].each do |event|
    unless event.is_a?(Hash)
      return LaunchDarkly::Result.fail("Invalid payload: 'events' must be a list of objects")
    end

    next unless event[:event]

    case event[:event].to_sym
    when LaunchDarkly::Interfaces::DataSystem::EventName::SERVER_INTENT
      begin
        server_intent = LaunchDarkly::Interfaces::DataSystem::ServerIntent.from_h(event[:data])
      rescue ArgumentError => e
        return LaunchDarkly::Result.fail("Invalid JSON in server intent", e)
      end

      if server_intent.payload.code == LaunchDarkly::Interfaces::DataSystem::IntentCode::TRANSFER_NONE
        return LaunchDarkly::Result.success(LaunchDarkly::Interfaces::DataSystem::ChangeSetBuilder.no_changes)
      end

      builder.start(server_intent.payload.code)

    when LaunchDarkly::Interfaces::DataSystem::EventName::PUT_OBJECT
      begin
        put = LaunchDarkly::Impl::DataSystem::ProtocolV2::PutObject.from_h(event[:data])
      rescue ArgumentError => e
        return LaunchDarkly::Result.fail("Invalid JSON in put object", e)
      end

      builder.add_put(put.kind, put.key, put.version, put.object)

    when LaunchDarkly::Interfaces::DataSystem::EventName::DELETE_OBJECT
      begin
        delete_object = LaunchDarkly::Impl::DataSystem::ProtocolV2::DeleteObject.from_h(event[:data])
      rescue ArgumentError => e
        return LaunchDarkly::Result.fail("Invalid JSON in delete object", e)
      end

      builder.add_delete(delete_object.kind, delete_object.key, delete_object.version)

    when LaunchDarkly::Interfaces::DataSystem::EventName::PAYLOAD_TRANSFERRED
      begin
        selector = LaunchDarkly::Interfaces::DataSystem::Selector.from_h(event[:data])
        changeset = builder.finish(selector)
        return LaunchDarkly::Result.success(changeset)
      rescue ArgumentError, RuntimeError => e
        return LaunchDarkly::Result.fail("Invalid JSON in payload transferred object", e)
      end
    end
  end

  LaunchDarkly::Result.fail("didn't receive any known protocol events in polling payload")
end

Instance Method Details

#data_availabilitySymbol

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Indicates what form of data is currently available.

This is calculated dynamically based on current system state.

Returns:

Raises:

Since:

  • 5.5.0

API:

  • private



89
90
91
# File 'lib/ldclient-rb/impl/data_system.rb', line 89

def data_availability
  raise NotImplementedError, "#{self.class} must implement #data_availability"
end

#data_source_status_providerLaunchDarkly::Interfaces::DataSource::StatusProvider

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns an interface for tracking the status of the data source.

The data source is the mechanism that the SDK uses to get feature flag configurations, such as a streaming connection (the default) or poll requests.

Returns:

Raises:

Since:

  • 5.5.0

API:

  • private



51
52
53
# File 'lib/ldclient-rb/impl/data_system.rb', line 51

def data_source_status_provider
  raise NotImplementedError, "#{self.class} must implement #data_source_status_provider"
end

#data_store_status_providerLaunchDarkly::Interfaces::DataStore::StatusProvider

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns an interface for tracking the status of a persistent data store.

The provider has methods for checking whether the data store is (as far as the SDK knows) currently operational, tracking changes in this status, and getting cache statistics. These are only relevant for a persistent data store; if you are using an in-memory data store, then this method will return a stub object that provides no information.

Returns:

Raises:

Since:

  • 5.5.0

API:

  • private



66
67
68
# File 'lib/ldclient-rb/impl/data_system.rb', line 66

def data_store_status_provider
  raise NotImplementedError, "#{self.class} must implement #data_store_status_provider"
end

#flag_change_broadcasterLaunchDarkly::Impl::Broadcaster

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the broadcaster for flag change notifications.

Consumers can use this broadcaster to build their own flag tracker or listen for flag changes directly.

Returns:

Raises:

Since:

  • 5.5.0

API:

  • private



78
79
80
# File 'lib/ldclient-rb/impl/data_system.rb', line 78

def flag_change_broadcaster
  raise NotImplementedError, "#{self.class} must implement #flag_change_broadcaster"
end

#set_diagnostic_accumulator(diagnostic_accumulator) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Sets the diagnostic accumulator for streaming initialization metrics. This should be called before start() to ensure metrics are collected.

Parameters:

  • The diagnostic accumulator

Raises:

Since:

  • 5.5.0

API:

  • private



118
119
120
# File 'lib/ldclient-rb/impl/data_system.rb', line 118

def set_diagnostic_accumulator(diagnostic_accumulator)
  raise NotImplementedError, "#{self.class} must implement #set_diagnostic_accumulator"
end

#startConcurrent::Event

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Starts the data system.

This method will return immediately. The returned event will be set when the system has reached an initial state (either permanently failed, e.g. due to bad auth, or succeeded).

If called multiple times, returns the same event as the first call.

Returns:

  • Event that will be set when initialization is complete

Raises:

Since:

  • 5.5.0

API:

  • private



29
30
31
# File 'lib/ldclient-rb/impl/data_system.rb', line 29

def start
  raise NotImplementedError, "#{self.class} must implement #start"
end

#stopvoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Halts the data system. Should be called when the client is closed to stop any long running operations. Makes the data system no longer usable.

Raises:

Since:

  • 5.5.0

API:

  • private



39
40
41
# File 'lib/ldclient-rb/impl/data_system.rb', line 39

def stop
  raise NotImplementedError, "#{self.class} must implement #stop"
end

#storeObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the data store used by the data system.

Returns:

  • The read-only store

Raises:

Since:

  • 5.5.0

API:

  • private



107
108
109
# File 'lib/ldclient-rb/impl/data_system.rb', line 107

def store
  raise NotImplementedError, "#{self.class} must implement #store"
end

#target_availabilitySymbol

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Indicates the ideal form of data attainable given the current configuration.

Returns:

  • one of the #DataAvailability constants

Raises:

Since:

  • 5.5.0

API:

  • private



98
99
100
# File 'lib/ldclient-rb/impl/data_system.rb', line 98

def target_availability
  raise NotImplementedError, "#{self.class} must implement #target_availability"
end