Skip to content

fix: allow for specification of initial reconnect delay in streaming data source #229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions contract-tests/sdk-contract-tests/src/entity_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,20 @@ std::optional<std::string> EntityManager::create(ConfigParams const& in) {
endpoints.EventsBaseUrl(*in.serviceEndpoints->events);
}
}
auto& datasource = config_builder.DataSource();

if (in.streaming) {
if (in.streaming->baseUri) {
endpoints.StreamingBaseUrl(*in.streaming->baseUri);
}
if (in.streaming->initialRetryDelayMs) {
auto streaming = DataSourceBuilder::Streaming();
streaming.InitialReconnectDelay(
std::chrono::milliseconds(*in.streaming->initialRetryDelayMs));
datasource.Method(std::move(streaming));
}
}

auto& datasource = config_builder.DataSource();

if (in.polling) {
if (in.polling->baseUri) {
endpoints.PollingBaseUrl(*in.polling->baseUri);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ void StreamingDataSource::Start() {
return;
}

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

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

client_builder.connect_timeout(http_config_.ConnectTimeout());

client_builder.initial_reconnect_delay(
streaming_config.initial_reconnect_delay);

for (auto const& header : http_config_.BaseHeaders()) {
client_builder.header(header.first, header.second);
}
Expand Down
9 changes: 9 additions & 0 deletions libs/server-sent-events/include/launchdarkly/sse/client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ class Builder {
*/
Builder& write_timeout(std::chrono::milliseconds timeout);

/**
* Specifies the initial delay before reconnection when backoff takes place
* due to an error on the connection.
* @param timeout
* @return Reference to this builder.
*/
Builder& initial_reconnect_delay(std::chrono::milliseconds delay);

/**
* Specify the method for the initial request. The default method is GET.
* @param verb The HTTP method.
Expand Down Expand Up @@ -138,6 +146,7 @@ class Builder {
std::optional<std::chrono::milliseconds> read_timeout_;
std::optional<std::chrono::milliseconds> write_timeout_;
std::optional<std::chrono::milliseconds> connect_timeout_;
std::optional<std::chrono::milliseconds> initial_reconnect_delay_;
LogCallback logging_cb_;
EventReceiver receiver_;
ErrorCallback error_cb_;
Expand Down
22 changes: 19 additions & 3 deletions libs/server-sent-events/src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ auto const kDefaultUserAgent = BOOST_BEAST_VERSION_STRING;
// Time duration used when no timeout is specified (1 year).
auto const kNoTimeout = std::chrono::hours(8760);

// Time duration that the backoff algorithm uses before initiating a new
// connection, the first time a failure is detected.
auto const kDefaultInitialReconnectDelay = std::chrono::seconds(1);

// Maximum duration between backoff attempts.
auto const kDefaultMaxBackoffDelay = std::chrono::seconds(30);

static boost::optional<net::ssl::context&> ToOptRef(
std::optional<net::ssl::context>& maybe_val) {
if (maybe_val) {
Expand All @@ -60,6 +67,7 @@ class FoxyClient : public Client,
std::optional<std::chrono::milliseconds> connect_timeout,
std::optional<std::chrono::milliseconds> read_timeout,
std::optional<std::chrono::milliseconds> write_timeout,
std::optional<std::chrono::milliseconds> initial_reconnect_delay,
Builder::EventReceiver receiver,
Builder::LogCallback logger,
Builder::ErrorCallback errors,
Expand All @@ -75,7 +83,9 @@ class FoxyClient : public Client,
launchdarkly::foxy::session_opts{
ToOptRef(ssl_context_),
connect_timeout.value_or(kNoTimeout)}),
backoff_(std::chrono::seconds(1), std::chrono::seconds(30)),
backoff_(
initial_reconnect_delay.value_or(kDefaultInitialReconnectDelay),
kDefaultMaxBackoffDelay),
last_event_id_(std::nullopt),
backoff_timer_(session_.get_executor()),
event_receiver_(std::move(receiver)),
Expand Down Expand Up @@ -347,6 +357,7 @@ Builder::Builder(net::any_io_executor ctx, std::string url)
read_timeout_{std::nullopt},
write_timeout_{std::nullopt},
connect_timeout_{std::nullopt},
initial_reconnect_delay_{std::nullopt},
logging_cb_([](auto msg) {}),
receiver_([](launchdarkly::sse::Event const&) {}),
error_cb_([](auto err) {}) {
Expand Down Expand Up @@ -382,6 +393,11 @@ Builder& Builder::write_timeout(std::chrono::milliseconds timeout) {
return *this;
}

Builder& Builder::initial_reconnect_delay(std::chrono::milliseconds delay) {
initial_reconnect_delay_ = delay;
return *this;
}

Builder& Builder::method(http::verb verb) {
request_.method(verb);
return *this;
Expand Down Expand Up @@ -441,8 +457,8 @@ std::shared_ptr<Client> Builder::build() {

return std::make_shared<FoxyClient>(
net::make_strand(executor_), request, host, service, connect_timeout_,
read_timeout_, write_timeout_, receiver_, logging_cb_, error_cb_,
std::move(ssl));
read_timeout_, write_timeout_, initial_reconnect_delay_, receiver_,
logging_cb_, error_cb_, std::move(ssl));
}

} // namespace launchdarkly::sse