1212using launchdarkly::LogLevel;
1313using namespace launchdarkly ::server_side;
1414
15- EntityManager::EntityManager (boost::asio::any_io_executor executor,
16- launchdarkly::Logger& logger)
17- : counter_{0 }, executor_{std::move (executor)}, logger_{logger} {}
18-
19- std::optional<std::string> EntityManager::create (ConfigParams const & in) {
20- std::string id = std::to_string (counter_++);
21-
22- auto config_builder = ConfigBuilder (in.credential );
23-
24- // The contract test service sets endpoints in a way that is disallowed
25- // for users. Specifically, it may set just 1 of the 3 endpoints, whereas
26- // we require all 3 to be set.
27- //
28- // To avoid that error being detected, we must configure the Endpoints
29- // builder with the 3 default URLs, which we can fetch by just calling Build
30- // on a new builder. That way when the contract tests set just 1 URL,
31- // the others have already been "set" so no error occurs.
32- auto const default_endpoints =
33- *config::builders::EndpointsBuilder ().Build ();
15+ namespace {
16+
17+ config::builders::DataSystemBuilder::FDv2 BuildFDv2 (
18+ ConfigDataSystemParams const & cfg,
19+ config::builders::EndpointsBuilder* endpoints) {
20+ auto fdv2 = config::builders::DataSystemBuilder::FDv2::Custom ();
21+
22+ if (cfg.synchronizers ) {
23+ for (auto const & sync : *cfg.synchronizers ) {
24+ if (sync.streaming ) {
25+ auto s = decltype (fdv2)::Streaming ();
26+ if (sync.streaming ->baseUri ) {
27+ s.BaseUrl (*sync.streaming ->baseUri );
28+ }
29+ if (sync.streaming ->initialRetryDelayMs ) {
30+ s.InitialReconnectDelay (std::chrono::milliseconds (
31+ *sync.streaming ->initialRetryDelayMs ));
32+ }
33+ fdv2.Synchronizer (std::move (s));
34+ } else if (sync.polling ) {
35+ auto p = decltype (fdv2)::Polling ();
36+ if (sync.polling ->baseUri ) {
37+ p.BaseUrl (*sync.polling ->baseUri );
38+ }
39+ if (sync.polling ->pollIntervalMs ) {
40+ p.PollInterval (
41+ std::chrono::duration_cast<std::chrono::seconds>(
42+ std::chrono::milliseconds (
43+ *sync.polling ->pollIntervalMs )));
44+ }
45+ fdv2.Synchronizer (std::move (p));
46+ }
47+ }
48+ }
3449
35- auto & endpoints =
36- config_builder.ServiceEndpoints ()
37- .EventsBaseUrl (default_endpoints.EventsBaseUrl ())
38- .PollingBaseUrl (default_endpoints.PollingBaseUrl ())
39- .StreamingBaseUrl (default_endpoints.StreamingBaseUrl ());
50+ if (cfg.initializers ) {
51+ for (auto const & init : *cfg.initializers ) {
52+ if (init.polling ) {
53+ auto p = decltype (fdv2)::Polling ();
54+ if (init.polling ->baseUri ) {
55+ p.BaseUrl (*init.polling ->baseUri );
56+ }
57+ if (init.polling ->pollIntervalMs ) {
58+ p.PollInterval (
59+ std::chrono::duration_cast<std::chrono::seconds>(
60+ std::chrono::milliseconds (
61+ *init.polling ->pollIntervalMs )));
62+ }
63+ fdv2.Initializer (std::move (p));
64+ }
65+ }
66+ }
4067
41- if (in.serviceEndpoints ) {
42- if (in.serviceEndpoints ->streaming ) {
43- endpoints.StreamingBaseUrl (*in.serviceEndpoints ->streaming );
68+ using FDv2Builder = config::builders::DataSystemBuilder::FDv2;
69+ if (cfg.fdv1Fallback ) {
70+ if (cfg.fdv1Fallback ->baseUri ) {
71+ endpoints->PollingBaseUrl (*cfg.fdv1Fallback ->baseUri );
72+ } else if (cfg.synchronizers && !cfg.synchronizers ->empty ()) {
73+ // No explicit baseUri: derive from the synchronizers list, matching
74+ // the no-fdv1Fallback branch below.
75+ ConfigDataSynchronizerParams const * selected = nullptr ;
76+ for (auto const & sync : *cfg.synchronizers ) {
77+ if (sync.polling ) {
78+ selected = &sync;
79+ break ;
80+ }
81+ }
82+ if (!selected) {
83+ selected = &cfg.synchronizers ->front ();
84+ }
85+ if (selected->polling && selected->polling ->baseUri ) {
86+ endpoints->PollingBaseUrl (*selected->polling ->baseUri );
87+ } else if (selected->streaming && selected->streaming ->baseUri ) {
88+ endpoints->PollingBaseUrl (*selected->streaming ->baseUri );
89+ }
4490 }
45- if (in.serviceEndpoints ->polling ) {
46- endpoints.PollingBaseUrl (*in.serviceEndpoints ->polling );
91+ FDv2Builder::FDv1Polling p;
92+ if (cfg.fdv1Fallback ->pollIntervalMs ) {
93+ p.PollInterval (std::chrono::duration_cast<std::chrono::seconds>(
94+ std::chrono::milliseconds (*cfg.fdv1Fallback ->pollIntervalMs )));
4795 }
48- if (in.serviceEndpoints ->events ) {
49- endpoints.EventsBaseUrl (*in.serviceEndpoints ->events );
96+ fdv2.FDv1Fallback (std::move (p));
97+ } else if (cfg.synchronizers && !cfg.synchronizers ->empty ()) {
98+ // Derive an FDv1 fallback from the synchronizers list: prefer the
99+ // first polling sync, otherwise reuse the first synchronizer's
100+ // baseUri. The fallback is always polling. The fallback reads its
101+ // URL from the global ServiceEndpoints, so set the polling endpoint
102+ // to the selected baseUri.
103+ ConfigDataSynchronizerParams const * selected = nullptr ;
104+ for (auto const & sync : *cfg.synchronizers ) {
105+ if (sync.polling ) {
106+ selected = &sync;
107+ break ;
108+ }
50109 }
110+ if (!selected) {
111+ selected = &cfg.synchronizers ->front ();
112+ }
113+ FDv2Builder::FDv1Polling p;
114+ if (selected->polling ) {
115+ if (selected->polling ->baseUri ) {
116+ endpoints->PollingBaseUrl (*selected->polling ->baseUri );
117+ }
118+ if (selected->polling ->pollIntervalMs ) {
119+ p.PollInterval (std::chrono::duration_cast<std::chrono::seconds>(
120+ std::chrono::milliseconds (
121+ *selected->polling ->pollIntervalMs )));
122+ }
123+ } else if (selected->streaming && selected->streaming ->baseUri ) {
124+ endpoints->PollingBaseUrl (*selected->streaming ->baseUri );
125+ }
126+ fdv2.FDv1Fallback (std::move (p));
51127 }
128+
129+ return fdv2;
130+ }
131+
132+ config::builders::DataSystemBuilder::BackgroundSync BuildBackgroundSync (
133+ ConfigParams const & in,
134+ config::builders::EndpointsBuilder* endpoints) {
52135 auto datasystem = config::builders::DataSystemBuilder::BackgroundSync ();
53136
54137 if (in.streaming ) {
55138 if (in.streaming ->baseUri ) {
56- endpoints. StreamingBaseUrl (*in.streaming ->baseUri );
139+ endpoints-> StreamingBaseUrl (*in.streaming ->baseUri );
57140 }
58141 auto streaming = decltype (datasystem)::Streaming ();
59142 if (in.streaming ->initialRetryDelayMs ) {
@@ -68,7 +151,7 @@ std::optional<std::string> EntityManager::create(ConfigParams const& in) {
68151
69152 if (in.polling ) {
70153 if (in.polling ->baseUri ) {
71- endpoints. PollingBaseUrl (*in.polling ->baseUri );
154+ endpoints-> PollingBaseUrl (*in.polling ->baseUri );
72155 }
73156 if (!in.streaming ) {
74157 auto method = decltype (datasystem)::Polling ();
@@ -85,7 +168,55 @@ std::optional<std::string> EntityManager::create(ConfigParams const& in) {
85168 }
86169 }
87170
88- config_builder.DataSystem ().Method (std::move (datasystem));
171+ return datasystem;
172+ }
173+
174+ } // namespace
175+
176+ EntityManager::EntityManager (boost::asio::any_io_executor executor,
177+ launchdarkly::Logger& logger)
178+ : counter_{0 }, executor_{std::move (executor)}, logger_{logger} {}
179+
180+ std::optional<std::string> EntityManager::create (ConfigParams const & in) {
181+ std::string id = std::to_string (counter_++);
182+
183+ auto config_builder = ConfigBuilder (in.credential );
184+
185+ // The contract test service sets endpoints in a way that is disallowed
186+ // for users. Specifically, it may set just 1 of the 3 endpoints, whereas
187+ // we require all 3 to be set.
188+ //
189+ // To avoid that error being detected, we must configure the Endpoints
190+ // builder with the 3 default URLs, which we can fetch by just calling Build
191+ // on a new builder. That way when the contract tests set just 1 URL,
192+ // the others have already been "set" so no error occurs.
193+ auto const default_endpoints =
194+ *config::builders::EndpointsBuilder ().Build ();
195+
196+ auto & endpoints =
197+ config_builder.ServiceEndpoints ()
198+ .EventsBaseUrl (default_endpoints.EventsBaseUrl ())
199+ .PollingBaseUrl (default_endpoints.PollingBaseUrl ())
200+ .StreamingBaseUrl (default_endpoints.StreamingBaseUrl ());
201+
202+ if (in.serviceEndpoints ) {
203+ if (in.serviceEndpoints ->streaming ) {
204+ endpoints.StreamingBaseUrl (*in.serviceEndpoints ->streaming );
205+ }
206+ if (in.serviceEndpoints ->polling ) {
207+ endpoints.PollingBaseUrl (*in.serviceEndpoints ->polling );
208+ }
209+ if (in.serviceEndpoints ->events ) {
210+ endpoints.EventsBaseUrl (*in.serviceEndpoints ->events );
211+ }
212+ }
213+
214+ if (in.dataSystem ) {
215+ config_builder.DataSystem ().Method (
216+ BuildFDv2 (*in.dataSystem , &endpoints));
217+ } else {
218+ config_builder.DataSystem ().Method (BuildBackgroundSync (in, &endpoints));
219+ }
89220
90221 auto & event_config = config_builder.Events ();
91222
0 commit comments