Skip to content

Commit d2cbf8e

Browse files
authored
feat: Implement data source configuration. (#18)
1 parent 356bde1 commit d2cbf8e

13 files changed

+597
-6
lines changed

libs/common/include/config/detail/config.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#pragma once
22

3+
#include "config/detail/data_source_config.hpp"
34
#include "config/detail/endpoints_builder.hpp"
45
#include "config/detail/events_builder.hpp"
6+
#include "config/detail/http_properties.hpp"
57

68
namespace launchdarkly::config::detail {
79

@@ -17,11 +19,15 @@ struct Config {
1719
detail::EndpointsBuilder<SDK> service_endpoints_builder;
1820
std::optional<std::string> application_tag;
1921
detail::EventsBuilder<SDK> events_builder;
22+
DataSourceConfig<SDK> data_source_config;
23+
detail::HttpProperties http_properties;
2024
Config(std::string sdk_key,
2125
bool offline,
2226
detail::EndpointsBuilder<SDK> service_endpoints_builder,
2327
detail::EventsBuilder<SDK> events_builder,
24-
std::optional<std::string> application_tag);
28+
std::optional<std::string> application_tag,
29+
DataSourceConfig<SDK> data_source_config,
30+
detail::HttpProperties http_properties);
2531
};
2632

2733
} // namespace launchdarkly::config::detail

libs/common/include/config/detail/config_builder.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
#include <string>
55
#include "config/detail/application_info.hpp"
66
#include "config/detail/config.hpp"
7+
#include "config/detail/data_source_builder.hpp"
78
#include "config/detail/endpoints_builder.hpp"
89
#include "config/detail/events_builder.hpp"
10+
#include "config/detail/http_properties_builder.hpp"
911
#include "logger.hpp"
1012

1113
namespace launchdarkly::config::detail {
@@ -21,6 +23,8 @@ class ConfigBuilder {
2123
using EndpointsBuilder = detail::EndpointsBuilder<SDK>;
2224
using EventsBuilder = detail::EventsBuilder<SDK>;
2325
using ConfigType = detail::Config<SDK>;
26+
using DataSourceBuilder = detail::DataSourceBuilder<SDK>;
27+
using HttpPropertiesBuilder = detail::HttpPropertiesBuilder<SDK>;
2428
/**
2529
* A minimal configuration consists of a LaunchDarkly SDK Key.
2630
* @param sdk_key SDK Key.
@@ -59,6 +63,22 @@ class ConfigBuilder {
5963
*/
6064
ConfigBuilder& events(EventsBuilder builder);
6165

66+
/**
67+
* Sets the configuration of the component that receives feature flag data
68+
* from LaunchDarkly.
69+
* @param builder A DataSourceConfig builder.
70+
* @return Reference to this builder.
71+
*/
72+
ConfigBuilder& data_source(detail::DataSourceBuilder<SDK> builder);
73+
74+
/**
75+
* Sets the SDK's networking configuration, using an HttpPropertiesBuilder.
76+
* The builder has methods for setting individual HTTP-related properties.
77+
* @param builder A HttpPropertiesBuilder builder.
78+
* @return Reference to this builder.
79+
*/
80+
ConfigBuilder& http_properties(detail::HttpPropertiesBuilder<SDK> builder);
81+
6282
/**
6383
* Builds a Configuration, suitable for passing into an instance of Client.
6484
* @return
@@ -71,6 +91,8 @@ class ConfigBuilder {
7191
std::optional<EndpointsBuilder> service_endpoints_builder_;
7292
std::optional<ApplicationInfo> application_info_builder_;
7393
std::optional<EventsBuilder> events_builder_;
94+
std::optional<DataSourceBuilder> data_source_builder_;
95+
std::optional<HttpPropertiesBuilder> http_properties_builder_;
7496
};
7597

7698
} // namespace launchdarkly::config::detail
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
#pragma once
2+
3+
#include <chrono>
4+
#include <optional>
5+
#include <type_traits>
6+
7+
#include "config/detail/data_source_config.hpp"
8+
#include "config/detail/defaults.hpp"
9+
#include "config/detail/sdks.hpp"
10+
11+
#include <boost/variant.hpp>
12+
13+
namespace launchdarkly::config::detail {
14+
15+
/**
16+
* Used to construct a DataSourceConfiguration for the specified SDK type.
17+
* @tparam SDK ClientSDK or ServerSDK.
18+
*/
19+
template <typename SDK>
20+
class DataSourceBuilder;
21+
22+
/**
23+
* Builds a configuration for a streaming data source.
24+
*/
25+
class StreamingBuilder {
26+
public:
27+
StreamingBuilder();
28+
29+
/**
30+
* Sets the initial reconnect delay for the streaming connection.
31+
*
32+
* The streaming service uses a backoff algorithm (with jitter) every time
33+
* the connection needs to be reestablished.The delay for the first
34+
* reconnection will start near this value, and then increase exponentially
35+
* for any subsequent connection failures.
36+
*
37+
* @param initial_reconnect_delay The initial delay for a reconnection
38+
* attempt.
39+
* @return Reference to this builder.
40+
*/
41+
StreamingBuilder& initial_reconnect_delay(
42+
std::chrono::milliseconds initial_reconnect_delay);
43+
44+
/**
45+
* Build the streaming config. Used internal to the SDK.
46+
* @return The built config.
47+
*/
48+
[[nodiscard]] StreamingConfig build() const;
49+
50+
private:
51+
StreamingConfig config_;
52+
};
53+
54+
/**
55+
* Contains methods for configuring the polling data source.
56+
*/
57+
class PollingBuilder {
58+
public:
59+
PollingBuilder();
60+
61+
/**
62+
* Sets the interval at which the SDK will poll for feature flag updates.
63+
* @param poll_interval The polling interval.
64+
* @return Reference to this builder.
65+
*/
66+
PollingBuilder& poll_interval(std::chrono::seconds poll_interval);
67+
68+
/**
69+
* Build the polling config. Used internal to the SDK.
70+
* @return The built config.
71+
*/
72+
[[nodiscard]] PollingConfig build() const;
73+
74+
private:
75+
PollingConfig config_;
76+
};
77+
78+
/**
79+
* The method visitor is only needed inside this file
80+
*/
81+
namespace {
82+
struct MethodVisitor {
83+
boost::variant<StreamingConfig, PollingConfig> operator()(
84+
StreamingBuilder streaming) {
85+
return streaming.build();
86+
}
87+
boost::variant<StreamingConfig, PollingConfig> operator()(
88+
PollingBuilder polling) {
89+
return polling.build();
90+
}
91+
};
92+
} // namespace
93+
94+
template <>
95+
class DataSourceBuilder<ClientSDK> {
96+
public:
97+
using Streaming = StreamingBuilder;
98+
using Polling = PollingBuilder;
99+
100+
DataSourceBuilder();
101+
102+
/**
103+
* Whether LaunchDarkly should provide additional information about how flag
104+
* values were calculated.
105+
*
106+
* The additional information will then be available through the client's
107+
* {TODO variation detail} method. Since this increases the size of network
108+
* requests, such information is not sent unless you set this option to
109+
* true.
110+
* @param value True to enable reasons.
111+
* @return Reference to this builder.
112+
*/
113+
DataSourceBuilder& with_reasons(bool value);
114+
115+
/**
116+
* Whether or not to use the REPORT verb to fetch flag settings.
117+
*
118+
* If this is true, flag settings will be fetched with a REPORT request
119+
* including a JSON entity body with the context object.
120+
*
121+
* Otherwise (by default) a GET request will be issued with the context
122+
* passed as a base64 URL-encoded path parameter.
123+
*
124+
* Do not use unless advised by LaunchDarkly.
125+
* @param value True to enable using the REPORT verb.
126+
* @return Reference to this builder.
127+
*/
128+
DataSourceBuilder& use_report(bool value);
129+
130+
/**
131+
* Set the streaming configuration for the builder.
132+
*
133+
* A data source may either be streaming or polling. Setting a streaming
134+
* builder indicates the data source will use streaming. Setting a polling
135+
* builder will indicate the use of polling.
136+
*
137+
* @param stream_builder The streaming builder.
138+
* @return Reference to this builder.
139+
*/
140+
DataSourceBuilder& method(Streaming stream_builder);
141+
142+
/**
143+
* Set the polling configuration for the builder.
144+
*
145+
* A data source may either be streaming or polling. Setting a stream
146+
* builder indicates the data source will use streaming. Setting a polling
147+
* builder will indicate the use of polling.
148+
*
149+
* @param polling_builder The polling builder.
150+
* @return Reference to this builder.
151+
*/
152+
DataSourceBuilder& method(Polling polling_builder);
153+
154+
/**
155+
* Build a data source config. This is used internal to the SDK.
156+
*
157+
* @return The built config.
158+
*/
159+
[[nodiscard]] DataSourceConfig<ClientSDK> build() const;
160+
161+
private:
162+
boost::variant<Streaming, Polling> method_;
163+
bool with_reasons_;
164+
bool use_report_;
165+
};
166+
167+
template <>
168+
class DataSourceBuilder<ServerSDK> {
169+
public:
170+
using Streaming = StreamingBuilder;
171+
using Polling = PollingBuilder;
172+
173+
DataSourceBuilder();
174+
175+
/**
176+
* Set the streaming configuration for the builder.
177+
*
178+
* A data source may either be streaming or polling. Setting a streaming
179+
* builder indicates the data source will use streaming. Setting a polling
180+
* builder will indicate the use of polling.
181+
*
182+
* @param stream_builder The streaming builder.
183+
* @return Reference to this builder.
184+
*/
185+
DataSourceBuilder& method(Streaming builder);
186+
187+
/**
188+
* Set the polling configuration for the builder.
189+
*
190+
* A data source may either be streaming or polling. Setting a stream
191+
* builder indicates the data source will use streaming. Setting a polling
192+
* builder will indicate the use of polling.
193+
*
194+
* @param polling_builder The polling builder.
195+
* @return Reference to this builder.
196+
*/
197+
DataSourceBuilder& method(Polling builder);
198+
199+
/**
200+
* Build a data source config. This is used internal to the SDK.
201+
*
202+
* @return The built config.
203+
*/
204+
[[nodiscard]] DataSourceConfig<ServerSDK> build() const;
205+
206+
private:
207+
boost::variant<Streaming, Polling> method_;
208+
bool with_reasons_;
209+
bool use_report_;
210+
};
211+
212+
} // namespace launchdarkly::config::detail
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#pragma once
2+
3+
#include <boost/variant.hpp>
4+
#include <chrono>
5+
#include <optional>
6+
#include <type_traits>
7+
#include "config/detail/sdks.hpp"
8+
9+
namespace launchdarkly::config::detail {
10+
11+
struct StreamingConfig {
12+
std::chrono::milliseconds initial_reconnect_delay;
13+
};
14+
15+
struct PollingConfig {
16+
std::chrono::seconds poll_interval;
17+
};
18+
19+
template <typename SDK>
20+
struct DataSourceConfig;
21+
22+
template <>
23+
struct DataSourceConfig<ClientSDK> {
24+
boost::variant<StreamingConfig, PollingConfig> method;
25+
26+
bool with_reasons;
27+
bool use_report;
28+
};
29+
30+
template <>
31+
struct DataSourceConfig<ServerSDK> {
32+
boost::variant<StreamingConfig, PollingConfig> method;
33+
};
34+
35+
} // namespace launchdarkly::config::detail

libs/common/include/config/detail/defaults.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include "config/detail/data_source_config.hpp"
34
#include "config/detail/events.hpp"
45
#include "config/detail/http_properties.hpp"
56
#include "config/detail/sdks.hpp"
@@ -19,6 +20,15 @@ struct Defaults {
1920
* @return
2021
*/
2122
static bool offline() { return false; }
23+
24+
static StreamingConfig streaming_config() {
25+
return {std::chrono::milliseconds{1000}};
26+
}
27+
28+
static PollingConfig polling_config() {
29+
// Default to 5 minutes;
30+
return {std::chrono::seconds{5 * 60}};
31+
}
2232
};
2333

2434
template <>
@@ -42,6 +52,10 @@ struct Defaults<ClientSDK> {
4252
sdk_name() + "/" + sdk_version(),
4353
std::map<std::string, std::string>()};
4454
}
55+
56+
static DataSourceConfig<ClientSDK> data_source_config() {
57+
return {Defaults<AnySDK>::streaming_config(), false, false};
58+
}
4559
};
4660

4761
template <>
@@ -65,6 +79,10 @@ struct Defaults<ServerSDK> {
6579
sdk_name() + "/" + sdk_version(),
6680
std::map<std::string, std::string>()};
6781
}
82+
83+
static DataSourceConfig<ServerSDK> data_source_config() {
84+
return {Defaults<AnySDK>::streaming_config()};
85+
}
6886
};
6987

7088
} // namespace launchdarkly::config::detail

libs/common/include/config/detail/http_properties_builder.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class HttpPropertiesBuilder {
2727
HttpPropertiesBuilder& custom_headers(
2828
std::map<std::string, std::string> base_headers);
2929

30-
HttpProperties build() const;
30+
[[nodiscard]] HttpProperties build() const;
3131

3232
private:
3333
std::chrono::milliseconds connect_timeout_{};

libs/common/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ add_library(${LIBNAME}
4343
events/conn_pool.cpp
4444
events/summary_state.cpp
4545
config/http_properties.cpp
46+
config/data_source_builder.cpp
4647
config/http_properties_builder.cpp)
4748

4849

0 commit comments

Comments
 (0)