Skip to content

Commit d1dde79

Browse files
authored
fix: allow for specification of initial reconnect delay in streaming data source (#229)
The public API was already available, but we didn't have the plumbing required to get it into the SSE client.
1 parent 054df6f commit d1dde79

File tree

4 files changed

+38
-6
lines changed

4 files changed

+38
-6
lines changed

contract-tests/sdk-contract-tests/src/entity_manager.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,20 @@ std::optional<std::string> EntityManager::create(ConfigParams const& in) {
4848
endpoints.EventsBaseUrl(*in.serviceEndpoints->events);
4949
}
5050
}
51+
auto& datasource = config_builder.DataSource();
5152

5253
if (in.streaming) {
5354
if (in.streaming->baseUri) {
5455
endpoints.StreamingBaseUrl(*in.streaming->baseUri);
5556
}
57+
if (in.streaming->initialRetryDelayMs) {
58+
auto streaming = DataSourceBuilder::Streaming();
59+
streaming.InitialReconnectDelay(
60+
std::chrono::milliseconds(*in.streaming->initialRetryDelayMs));
61+
datasource.Method(std::move(streaming));
62+
}
5663
}
5764

58-
auto& datasource = config_builder.DataSource();
59-
6065
if (in.polling) {
6166
if (in.polling->baseUri) {
6267
endpoints.PollingBaseUrl(*in.polling->baseUri);

libs/client-sdk/src/data_sources/streaming_data_source.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ void StreamingDataSource::Start() {
9191
return;
9292
}
9393

94-
// TODO: Initial reconnect delay. sc-204393
9594
boost::urls::url url = uri_components.value();
9695

9796
if (data_source_config_.with_reasons) {
@@ -117,6 +116,9 @@ void StreamingDataSource::Start() {
117116

118117
client_builder.connect_timeout(http_config_.ConnectTimeout());
119118

119+
client_builder.initial_reconnect_delay(
120+
streaming_config.initial_reconnect_delay);
121+
120122
for (auto const& header : http_config_.BaseHeaders()) {
121123
client_builder.header(header.first, header.second);
122124
}

libs/server-sent-events/include/launchdarkly/sse/client.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ class Builder {
9090
*/
9191
Builder& write_timeout(std::chrono::milliseconds timeout);
9292

93+
/**
94+
* Specifies the initial delay before reconnection when backoff takes place
95+
* due to an error on the connection.
96+
* @param timeout
97+
* @return Reference to this builder.
98+
*/
99+
Builder& initial_reconnect_delay(std::chrono::milliseconds delay);
100+
93101
/**
94102
* Specify the method for the initial request. The default method is GET.
95103
* @param verb The HTTP method.
@@ -138,6 +146,7 @@ class Builder {
138146
std::optional<std::chrono::milliseconds> read_timeout_;
139147
std::optional<std::chrono::milliseconds> write_timeout_;
140148
std::optional<std::chrono::milliseconds> connect_timeout_;
149+
std::optional<std::chrono::milliseconds> initial_reconnect_delay_;
141150
LogCallback logging_cb_;
142151
EventReceiver receiver_;
143152
ErrorCallback error_cb_;

libs/server-sent-events/src/client.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ auto const kDefaultUserAgent = BOOST_BEAST_VERSION_STRING;
3737
// Time duration used when no timeout is specified (1 year).
3838
auto const kNoTimeout = std::chrono::hours(8760);
3939

40+
// Time duration that the backoff algorithm uses before initiating a new
41+
// connection, the first time a failure is detected.
42+
auto const kDefaultInitialReconnectDelay = std::chrono::seconds(1);
43+
44+
// Maximum duration between backoff attempts.
45+
auto const kDefaultMaxBackoffDelay = std::chrono::seconds(30);
46+
4047
static boost::optional<net::ssl::context&> ToOptRef(
4148
std::optional<net::ssl::context>& maybe_val) {
4249
if (maybe_val) {
@@ -60,6 +67,7 @@ class FoxyClient : public Client,
6067
std::optional<std::chrono::milliseconds> connect_timeout,
6168
std::optional<std::chrono::milliseconds> read_timeout,
6269
std::optional<std::chrono::milliseconds> write_timeout,
70+
std::optional<std::chrono::milliseconds> initial_reconnect_delay,
6371
Builder::EventReceiver receiver,
6472
Builder::LogCallback logger,
6573
Builder::ErrorCallback errors,
@@ -75,7 +83,9 @@ class FoxyClient : public Client,
7583
launchdarkly::foxy::session_opts{
7684
ToOptRef(ssl_context_),
7785
connect_timeout.value_or(kNoTimeout)}),
78-
backoff_(std::chrono::seconds(1), std::chrono::seconds(30)),
86+
backoff_(
87+
initial_reconnect_delay.value_or(kDefaultInitialReconnectDelay),
88+
kDefaultMaxBackoffDelay),
7989
last_event_id_(std::nullopt),
8090
backoff_timer_(session_.get_executor()),
8191
event_receiver_(std::move(receiver)),
@@ -347,6 +357,7 @@ Builder::Builder(net::any_io_executor ctx, std::string url)
347357
read_timeout_{std::nullopt},
348358
write_timeout_{std::nullopt},
349359
connect_timeout_{std::nullopt},
360+
initial_reconnect_delay_{std::nullopt},
350361
logging_cb_([](auto msg) {}),
351362
receiver_([](launchdarkly::sse::Event const&) {}),
352363
error_cb_([](auto err) {}) {
@@ -382,6 +393,11 @@ Builder& Builder::write_timeout(std::chrono::milliseconds timeout) {
382393
return *this;
383394
}
384395

396+
Builder& Builder::initial_reconnect_delay(std::chrono::milliseconds delay) {
397+
initial_reconnect_delay_ = delay;
398+
return *this;
399+
}
400+
385401
Builder& Builder::method(http::verb verb) {
386402
request_.method(verb);
387403
return *this;
@@ -441,8 +457,8 @@ std::shared_ptr<Client> Builder::build() {
441457

442458
return std::make_shared<FoxyClient>(
443459
net::make_strand(executor_), request, host, service, connect_timeout_,
444-
read_timeout_, write_timeout_, receiver_, logging_cb_, error_cb_,
445-
std::move(ssl));
460+
read_timeout_, write_timeout_, initial_reconnect_delay_, receiver_,
461+
logging_cb_, error_cb_, std::move(ssl));
446462
}
447463

448464
} // namespace launchdarkly::sse

0 commit comments

Comments
 (0)