C++ Server-Side SDK
LaunchDarkly SDK
Public Member Functions | List of all members
launchdarkly::server_side::data_systems::FDv2DataSystem Class Referencefinal

#include <fdv2_data_system.hpp>

Inheritance diagram for launchdarkly::server_side::data_systems::FDv2DataSystem:
Inheritance graph
[legend]
Collaboration diagram for launchdarkly::server_side::data_systems::FDv2DataSystem:
Collaboration graph
[legend]

Public Member Functions

 FDv2DataSystem (std::vector< std::unique_ptr< data_interfaces::IFDv2InitializerFactory >> initializer_factories, std::vector< std::unique_ptr< data_interfaces::IFDv2SynchronizerFactory >> synchronizer_factories, std::unique_ptr< data_interfaces::IFDv2ConditionFactory > fallback_condition_factory, std::unique_ptr< data_interfaces::IFDv2ConditionFactory > recovery_condition_factory, boost::asio::any_io_executor ioc, data_components::DataSourceStatusManager *status_manager, Logger const &logger)
 
 FDv2DataSystem (FDv2DataSystem const &)=delete
 
 FDv2DataSystem (FDv2DataSystem &&)=delete
 
FDv2DataSystemoperator= (FDv2DataSystem const &)=delete
 
FDv2DataSystemoperator= (FDv2DataSystem &&)=delete
 
std::shared_ptr< data_model::FlagDescriptor > GetFlag (std::string const &key) const override
 
std::shared_ptr< data_model::SegmentDescriptor > GetSegment (std::string const &key) const override
 
std::unordered_map< std::string, std::shared_ptr< data_model::FlagDescriptor > > AllFlags () const override
 
std::unordered_map< std::string, std::shared_ptr< data_model::SegmentDescriptor > > AllSegments () const override
 
std::string const & Identity () const override
 
void Initialize () override
 
bool Initialized () const override
 
- Public Member Functions inherited from launchdarkly::server_side::data_interfaces::IDataSystem
 IDataSystem (IDataSystem const &item)=delete
 
 IDataSystem (IDataSystem &&item)=delete
 
IDataSystemoperator= (IDataSystem const &)=delete
 
IDataSystemoperator= (IDataSystem &&)=delete
 
- Public Member Functions inherited from launchdarkly::server_side::data_interfaces::IStore
 IStore (IStore const &item)=delete
 
 IStore (IStore &&item)=delete
 
IStoreoperator= (IStore const &)=delete
 
IStoreoperator= (IStore &&)=delete
 

Detailed Description

FDv2DataSystem is the IDataSystem implementation for the FDv2 protocol. It runs a sequence of initializers to populate an in-memory store, then hands off to a synchronizer for ongoing updates.

Lifecycle / call order:

  1. Construct.
  2. Call Initialize() exactly once. It returns immediately; orchestration runs asynchronously on the executor.
  3. Call IStore methods (GetFlag/GetSegment/AllFlags/AllSegments) and Initialized() / Identity() any number of times, from any thread.
  4. Drain the executor and join callers (see Destruction protocol).
  5. Destroy.

Initialize() may not be called more than once.

Thread safety:

Destruction protocol:

The destructor cancels in-flight orchestration (closes the active source) but does NOT block to drain executor callbacks that may already be queued. Before destroying, the caller must ensure both of:

  1. The executor that orchestration callbacks run on has been stopped AND any thread running it has been joined. Otherwise a previously- scheduled callback may run and reference a destroyed object.
  2. No other thread is currently calling a method on this object.

The standard pattern is:

ioc.stop();          // no new callbacks; running work returns
run_thread.join();   // wait for the executor thread to exit
// Now no thread can be touching this object.
// Destroy FDv2DataSystem.

ClientImpl's destructor uses this pattern (~ClientImpl performs ioc_.stop() and run_thread_.join() before any member is destroyed).

Sources (initializers and synchronizers):

Sources are constructed lazily via the factories supplied at construction. Each factory is invoked at most once during a run of the orchestration. A source is closed and destroyed when the orchestration finishes processing a result that ends its turn, or when the FDv2DataSystem is destroyed. At any given moment at most one source is active.

Selector tracking:

FDv2DataSystem tracks the most-recent non-empty selector seen on a ChangeSet and passes it into each subsequent synchronizer Next() call. The initial selector is empty.

Orchestration phases:

      Initialize()
          |
          v
+-------------------+   no factories given
|  Offline?         |---------> [Done, status = kValid]
+-------------------+
          |
          v
+-------------------+    initializer #N returns:
|  Initializer phase|      ChangeSet(no selector) -> stay, N += 1
|  N = 0, 1, 2, ... |      ChangeSet(selector)    -> go to Sync
|                   |      Interrupted/Terminal   -> stay, N += 1
|                   |      Goodbye                -> stay, N += 1
|                   |      Shutdown               -> [Closed]
+-------------------+
          |
          | (N exhausted, or basis received)
          v
+-------------------+    active synchronizer's Next returns:
|  Synchronizer     |      ChangeSet      -> apply, loop
|  phase            |      Interrupted    -> loop (source self-retries)
|  (cyclic;         |      Goodbye        -> loop (source self-restarts)
|   blocked sources |      TerminalError  -> block, advance
|   are skipped)    |      Shutdown       -> [Closed]
+-------------------+
              ^   |     fallback condition  -> advance (with wrap)
              |   |     recovery condition  -> reset to first available
              +---+
          |
          | (all synchronizers blocked)
          v
[Done; final status preserved]

Status transitions:

kInitializing (initial) -> kValid on first successful ChangeSet apply. kInterrupted on Interrupted / TerminalError (filtered to kInitializing while still in the initializer phase if not yet Valid). kOff if all initializers exhaust without data and no synchronizers are configured. kValid -> kInterrupted on errors; kOff when synchronizers cycle through and exhaust. kInterrupted -> kValid on next successful ChangeSet apply; kOff on synchronizer exhaustion. kOff -> terminal.

Constructor & Destructor Documentation

◆ FDv2DataSystem()

launchdarkly::server_side::data_systems::FDv2DataSystem::FDv2DataSystem ( std::vector< std::unique_ptr< data_interfaces::IFDv2InitializerFactory >>  initializer_factories,
std::vector< std::unique_ptr< data_interfaces::IFDv2SynchronizerFactory >>  synchronizer_factories,
std::unique_ptr< data_interfaces::IFDv2ConditionFactory fallback_condition_factory,
std::unique_ptr< data_interfaces::IFDv2ConditionFactory recovery_condition_factory,
boost::asio::any_io_executor  ioc,
data_components::DataSourceStatusManager status_manager,
Logger const &  logger 
)

Constructs the data system.

Parameters
initializer_factoriesFactories that build initializers, run in order during the initialization phase.
synchronizer_factoriesFactories that build synchronizers, used in order for ongoing updates after initialization.
fallback_condition_factoryFactory for the per-synchronizer fallback condition. May be null. If null, fallback transitions are never triggered; synchronizers only rotate on terminal errors.
recovery_condition_factoryFactory for the per-synchronizer recovery condition. May be null. If null, the orchestrator does not return to a more-preferred synchronizer once it has fallen back.
iocExecutor on which orchestration callbacks run.
status_managerNon-owning. Must outlive this object; the caller is responsible for ensuring this. Used to publish data-source status transitions.
loggerUsed for diagnostic logging. Held by value (Logger is internally thread-safe and cheap to copy).

Member Function Documentation

◆ AllFlags()

std::unordered_map< std::string, std::shared_ptr< data_model::FlagDescriptor > > launchdarkly::server_side::data_systems::FDv2DataSystem::AllFlags ( ) const
overridevirtual

Returns all flag descriptors currently in the store, keyed by flag key. The returned map is a snapshot; subsequent updates are not reflected.

Implements launchdarkly::server_side::data_interfaces::IStore.

◆ AllSegments()

std::unordered_map< std::string, std::shared_ptr< data_model::SegmentDescriptor > > launchdarkly::server_side::data_systems::FDv2DataSystem::AllSegments ( ) const
overridevirtual

Returns all segment descriptors currently in the store, keyed by segment key. The returned map is a snapshot; subsequent updates are not reflected.

Implements launchdarkly::server_side::data_interfaces::IStore.

◆ GetFlag()

std::shared_ptr< data_model::FlagDescriptor > launchdarkly::server_side::data_systems::FDv2DataSystem::GetFlag ( std::string const &  key) const
overridevirtual

Returns the flag descriptor for the given key, or nullptr if no flag with that key is currently in the store.

Implements launchdarkly::server_side::data_interfaces::IStore.

◆ GetSegment()

std::shared_ptr< data_model::SegmentDescriptor > launchdarkly::server_side::data_systems::FDv2DataSystem::GetSegment ( std::string const &  key) const
overridevirtual

Returns the segment descriptor for the given key, or nullptr if no segment with that key is currently in the store.

Implements launchdarkly::server_side::data_interfaces::IStore.

◆ Identity()

std::string const & launchdarkly::server_side::data_systems::FDv2DataSystem::Identity ( ) const
overridevirtual

Returns a display-suitable name for the data system, used in diagnostic logging.

Implements launchdarkly::server_side::data_interfaces::IDataSystem.

◆ Initialize()

void launchdarkly::server_side::data_systems::FDv2DataSystem::Initialize ( )
overridevirtual

Starts the orchestration: runs initializers in order on the executor, then hands off to a synchronizer for ongoing updates. Returns immediately; orchestration runs asynchronously. Must be called exactly once, before any IStore method is invoked.

Implements launchdarkly::server_side::data_interfaces::IDataSystem.

◆ Initialized()

bool launchdarkly::server_side::data_systems::FDv2DataSystem::Initialized ( ) const
overridevirtual

Returns true once the in-memory store has been populated for the first time. Naming follows the IDataSystem base interface (predates the IsX() convention).

Implements launchdarkly::server_side::data_interfaces::IStore.


The documentation for this class was generated from the following files: