|
C++ Server-Side SDK
LaunchDarkly SDK
|
#include <fdv2_data_system.hpp>


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 | |
| FDv2DataSystem & | operator= (FDv2DataSystem const &)=delete |
| FDv2DataSystem & | operator= (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 | |
| IDataSystem & | operator= (IDataSystem const &)=delete |
| IDataSystem & | operator= (IDataSystem &&)=delete |
Public Member Functions inherited from launchdarkly::server_side::data_interfaces::IStore | |
| IStore (IStore const &item)=delete | |
| IStore (IStore &&item)=delete | |
| IStore & | operator= (IStore const &)=delete |
| IStore & | operator= (IStore &&)=delete |
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:
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:
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.
| 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.
| initializer_factories | Factories that build initializers, run in order during the initialization phase. |
| synchronizer_factories | Factories that build synchronizers, used in order for ongoing updates after initialization. |
| fallback_condition_factory | Factory for the per-synchronizer fallback condition. May be null. If null, fallback transitions are never triggered; synchronizers only rotate on terminal errors. |
| recovery_condition_factory | Factory 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. |
| ioc | Executor on which orchestration callbacks run. |
| status_manager | Non-owning. Must outlive this object; the caller is responsible for ensuring this. Used to publish data-source status transitions. |
| logger | Used for diagnostic logging. Held by value (Logger is internally thread-safe and cheap to copy). |
|
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.
|
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.
|
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.
|
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.
|
overridevirtual |
Returns a display-suitable name for the data system, used in diagnostic logging.
Implements launchdarkly::server_side::data_interfaces::IDataSystem.
|
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.
|
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.