C++ Server-Side SDK
LaunchDarkly SDK
fdv1_adapter_synchronizer.hpp
1 #pragma once
2 
3 #include "../../data_components/status_notifications/data_source_status_manager.hpp"
4 #include "../../data_interfaces/destination/idestination.hpp"
5 #include "../../data_interfaces/source/idata_synchronizer.hpp"
6 #include "../../data_interfaces/source/ifdv2_synchronizer.hpp"
7 
8 #include <launchdarkly/async/promise.hpp>
9 #include <launchdarkly/connection.hpp>
10 
11 #include <deque>
12 #include <functional>
13 #include <memory>
14 #include <mutex>
15 #include <optional>
16 #include <string>
17 #include <variant>
18 
19 namespace launchdarkly::server_side::data_systems {
20 
37  public:
38  using SourceBuilder =
39  std::function<std::shared_ptr<data_interfaces::IDataSynchronizer>(
41 
48  explicit FDv1AdapterSynchronizer(SourceBuilder source_builder);
49 
50  ~FDv1AdapterSynchronizer() override;
51 
52  async::Future<data_interfaces::FDv2SourceResult> Next(
53  data_model::Selector selector) override;
54  void Close() override;
55  [[nodiscard]] std::string const& Identity() const override;
56 
57  private:
63  class State {
64  public:
65  explicit State(async::Future<std::monostate> closed_future);
66 
67  async::Future<data_interfaces::FDv2SourceResult> GetNext();
68 
69  // Resolves any pending Next() promise with Shutdown and clears it.
70  // Called on the close path so the abandoned promise doesn't leave
71  // potential continuations dangling.
72  void ResolvePendingAsShutdown();
73 
74  void Notify(data_interfaces::FDv2SourceResult result);
75 
76  private:
77  // Finished once the owning FDv1AdapterSynchronizer's close_promise_
78  // is resolved. Read in Notify to drop late results.
79  async::Future<std::monostate> const closed_future_;
80 
81  mutable std::mutex mutex_;
82  // Protected by mutex_.
83  std::optional<async::Promise<data_interfaces::FDv2SourceResult>>
84  pending_promise_;
85  std::deque<data_interfaces::FDv2SourceResult> result_queue_;
86  };
87 
92  class ConvertingDestination final : public data_interfaces::IDestination {
93  public:
94  explicit ConvertingDestination(std::weak_ptr<State> state);
95  void Init(data_model::SDKDataSet data_set) override;
96  void Upsert(std::string const& key,
97  data_model::FlagDescriptor flag) override;
98  void Upsert(std::string const& key,
99  data_model::SegmentDescriptor segment) override;
100  [[nodiscard]] std::string const& Identity() const override;
101 
102  private:
103  std::weak_ptr<State> state_;
104  };
105 
106  // Thread-safe primitive. Declared before state_ so state_'s constructor
107  // can take a future from it.
108  async::Promise<std::monostate> close_promise_;
109 
110  // shared_ptr so async callbacks that may fire after this is destroyed
111  // can hold their own reference.
112  std::shared_ptr<State> const state_;
113  std::unique_ptr<ConvertingDestination> const destination_;
114 
115  std::unique_ptr<data_components::DataSourceStatusManager> const
116  status_manager_;
117  std::unique_ptr<IConnection> const status_subscription_;
118 
119  std::shared_ptr<data_interfaces::IDataSynchronizer> const fdv1_source_;
120 
121  // Serializes StartAsync and ShutdownAsync on fdv1_source_ across
122  // concurrent Next() and Close() calls.
123  std::mutex lifecycle_mutex_;
124  // Protected by lifecycle_mutex_. Set when Next() calls StartAsync, or
125  // when Close() runs without a prior start (to gate any later Next()
126  // from calling StartAsync after Close).
127  bool started_ = false;
128 };
129 
130 } // namespace launchdarkly::server_side::data_systems
Definition: data_source_status_manager.hpp:16
IDestination represents a sink for data received by the SDK. A destination may be a database,...
Definition: idestination.hpp:14
Definition: fdv1_adapter_synchronizer.hpp:36
void Close() override
Definition: fdv1_adapter_synchronizer.cpp:191
FDv1AdapterSynchronizer(SourceBuilder source_builder)
Definition: fdv1_adapter_synchronizer.cpp:124
std::string const & Identity() const override
Definition: fdv1_adapter_synchronizer.cpp:203
async::Future< data_interfaces::FDv2SourceResult > Next(data_model::Selector selector) override
Definition: fdv1_adapter_synchronizer.cpp:158