C++ Server-Side SDK
LaunchDarkly SDK
fdv2_data_system.hpp
1 #pragma once
2 
3 #include "../../data_components/change_notifier/change_notifier.hpp"
4 #include "../../data_components/memory_store/memory_store.hpp"
5 #include "../../data_components/status_notifications/data_source_status_manager.hpp"
6 #include "../../data_interfaces/source/ifdv2_condition.hpp"
7 #include "../../data_interfaces/source/ifdv2_initializer_factory.hpp"
8 #include "../../data_interfaces/source/ifdv2_synchronizer_factory.hpp"
9 #include "../../data_interfaces/system/idata_system.hpp"
10 #include "conditions.hpp"
11 #include "source_manager.hpp"
12 
13 #include <launchdarkly/async/cancellation.hpp>
14 #include <launchdarkly/data_model/selector.hpp>
15 #include <launchdarkly/logging/logger.hpp>
16 
17 #include <boost/asio/any_io_executor.hpp>
18 
19 #include <atomic>
20 #include <chrono>
21 #include <cstddef>
22 #include <memory>
23 #include <mutex>
24 #include <vector>
25 
26 namespace launchdarkly::server_side::data_systems {
27 
139  public:
162  std::vector<std::unique_ptr<data_interfaces::IFDv2InitializerFactory>>
163  initializer_factories,
164  std::vector<std::unique_ptr<data_interfaces::IFDv2SynchronizerFactory>>
165  synchronizer_factories,
166  std::unique_ptr<data_interfaces::IFDv2ConditionFactory>
167  fallback_condition_factory,
168  std::unique_ptr<data_interfaces::IFDv2ConditionFactory>
169  recovery_condition_factory,
170  boost::asio::any_io_executor ioc,
172  Logger const& logger);
173 
174  ~FDv2DataSystem() override;
175 
176  FDv2DataSystem(FDv2DataSystem const&) = delete;
177  FDv2DataSystem(FDv2DataSystem&&) = delete;
178  FDv2DataSystem& operator=(FDv2DataSystem const&) = delete;
179  FDv2DataSystem& operator=(FDv2DataSystem&&) = delete;
180 
185  std::shared_ptr<data_model::FlagDescriptor> GetFlag(
186  std::string const& key) const override;
187 
192  std::shared_ptr<data_model::SegmentDescriptor> GetSegment(
193  std::string const& key) const override;
194 
199  std::unordered_map<std::string, std::shared_ptr<data_model::FlagDescriptor>>
200  AllFlags() const override;
201 
207  std::unordered_map<std::string,
208  std::shared_ptr<data_model::SegmentDescriptor>>
209  AllSegments() const override;
210 
215  std::string const& Identity() const override;
216 
223  void Initialize() override;
224 
230  bool Initialized() const override;
231 
232  private:
237  void Close();
238 
239  // Orchestration-loop methods. Each step chains the next via Future::Then,
240  // so at most one step has a pending continuation at any time. mutex_
241  // provides mutual exclusion for orchestration state when callbacks run on
242  // different executor threads, and lets Close() safely tear down active
243  // sources from any thread.
244 
245  void RunNextInitializer();
246  void OnInitializerResult(data_interfaces::FDv2SourceResult result);
247  void StartSynchronizers();
248  void RunSynchronizerNext();
249  void OnSynchronizerResult(data_interfaces::FDv2SourceResult result);
250  void OnConditionFired(data_interfaces::IFDv2Condition::Type type);
251 
252  // Schedules an FDv2 recovery attempt after the given TTL. Called with
253  // mutex_ held. TTL of 0 disables the recovery and is a no-op.
254  void ScheduleFDv2RetryLocked(std::chrono::seconds ttl);
255 
256  // Invoked when the FDv1 fallback TTL expires. Switches the source list
257  // back to FDv2 and restarts the synchronizer phase.
258  void OnFDv1RetryTimer();
259 
260  // Builds the conditions to apply to the currently active synchronizer.
261  // Must be called with mutex_ held; reads source_manager_ state.
262  std::unique_ptr<Conditions> BuildActiveConditions() const;
263 
264  // Applies a typed FDv2 changeset to the in-memory store and updates the
265  // tracked selector if the changeset's selector is non-empty.
266  void ApplyChangeSet(
267  data_model::ChangeSet<data_interfaces::ChangeSetData> change_set);
268 
269  // Logger is itself thread-safe and cheap to copy.
270  Logger logger_;
271 
272  // Immutable after construction.
273  boost::asio::any_io_executor const ioc_;
274  std::vector<std::unique_ptr<data_interfaces::IFDv2InitializerFactory>> const
275  initializer_factories_;
276  std::unique_ptr<data_interfaces::IFDv2ConditionFactory> const
277  fallback_condition_factory_;
278  std::unique_ptr<data_interfaces::IFDv2ConditionFactory> const
279  recovery_condition_factory_;
280  // Non-owning. Lifetime guaranteed by the caller (see constructor doc).
281  data_components::DataSourceStatusManager* const status_manager_;
282 
283  // Internally synchronized.
285  // Holds references to store_; declared after it so destruction order is
286  // safe.
287  data_components::ChangeNotifier change_notifier_;
288 
289  // Set by Initialize() to detect repeat or concurrent calls.
290  std::atomic_bool initialize_called_;
291 
292  // Suppresses consecutive "interrupted" logs from the active synchronizer.
293  std::atomic_bool last_logged_synchronizer_interrupted_;
294 
295  // Orchestration state, guarded by mutex_.
296  std::mutex mutex_;
297  bool closed_;
298  data_model::Selector selector_;
299  std::size_t initializer_index_;
300  SourceManager source_manager_;
301  std::unique_ptr<data_interfaces::IFDv2Initializer> active_initializer_;
302  std::unique_ptr<data_interfaces::IFDv2Synchronizer> active_synchronizer_;
303  std::unique_ptr<Conditions> active_conditions_;
304 
305  // Cancelled in Close() to abort any pending FDv1 fallback retry delay.
306  async::CancellationSource fdv1_fallback_retry_cancel_;
307 };
308 
309 } // namespace launchdarkly::server_side::data_systems
Definition: data_source_status_manager.hpp:16
IDataSystem obtains data used for flag evaluations and makes it available to other components.
Definition: idata_system.hpp:11
bool Initialized() const override
Definition: fdv2_data_system.cpp:486
std::string const & Identity() const override
Definition: fdv2_data_system.cpp:95
void Initialize() override
Definition: fdv2_data_system.cpp:100
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)
Definition: fdv2_data_system.cpp:26
std::shared_ptr< data_model::FlagDescriptor > GetFlag(std::string const &key) const override
Definition: fdv2_data_system.cpp:75
std::unordered_map< std::string, std::shared_ptr< data_model::SegmentDescriptor > > AllSegments() const override
Definition: fdv2_data_system.cpp:91
std::unordered_map< std::string, std::shared_ptr< data_model::FlagDescriptor > > AllFlags() const override
Definition: fdv2_data_system.cpp:86
std::shared_ptr< data_model::SegmentDescriptor > GetSegment(std::string const &key) const override
Definition: fdv2_data_system.cpp:80