@@ -79,20 +79,20 @@ class FoxyClient : public Client,
79
79
read_timeout_(read_timeout),
80
80
write_timeout_(write_timeout),
81
81
req_(std::move(req)),
82
- session_(std::move(executor),
83
- launchdarkly::foxy::session_opts{
84
- ToOptRef (ssl_context_),
85
- connect_timeout.value_or (kNoTimeout )}),
86
82
backoff_(
87
83
initial_reconnect_delay.value_or(kDefaultInitialReconnectDelay ),
88
84
kDefaultMaxBackoffDelay),
89
85
last_event_id_(std::nullopt),
90
- backoff_timer_(session_.get_executor( )),
86
+ backoff_timer_(std::move(executor )),
91
87
event_receiver_(std::move(receiver)),
92
88
logger_(std::move(logger)),
93
89
errors_(std::move(errors)),
94
- last_read_(std::nullopt) {
90
+ last_read_(std::nullopt),
91
+ shutting_down_(false ),
92
+ body_parser_(std::nullopt),
93
+ session_(std::nullopt) {
95
94
create_parser ();
95
+ create_session ();
96
96
}
97
97
98
98
/* * Logs a message indicating that an async_read_some operation
@@ -132,6 +132,13 @@ class FoxyClient : public Client,
132
132
body_parser_->get ().body ().on_event (event_receiver_);
133
133
}
134
134
135
+ void create_session () {
136
+ session_.emplace (
137
+ backoff_timer_.get_executor (),
138
+ launchdarkly::foxy::session_opts{
139
+ ToOptRef (ssl_context_), connect_timeout_.value_or (kNoTimeout )});
140
+ }
141
+
135
142
/* *
136
143
* Called whenever the connection needs to be reattempted, triggering
137
144
* a timed wait for the current backoff duration.
@@ -158,6 +165,8 @@ class FoxyClient : public Client,
158
165
logger_ (msg.str ());
159
166
160
167
create_parser ();
168
+ create_session ();
169
+
161
170
backoff_timer_.expires_from_now (backoff_.delay ());
162
171
backoff_timer_.async_wait (beast::bind_front_handler (
163
172
&FoxyClient::on_backoff, shared_from_this ()));
@@ -171,7 +180,7 @@ class FoxyClient : public Client,
171
180
}
172
181
173
182
void run () override {
174
- session_. async_connect (
183
+ session_-> async_connect (
175
184
host_, port_,
176
185
beast::bind_front_handler (&FoxyClient::on_connect,
177
186
shared_from_this ()));
@@ -190,10 +199,10 @@ class FoxyClient : public Client,
190
199
} else {
191
200
req_.erase (" last-event-id" );
192
201
}
193
- session_. opts .timeout = write_timeout_.value_or (kNoTimeout );
194
- session_. async_write (req_,
195
- beast::bind_front_handler (&FoxyClient::on_write,
196
- shared_from_this ()));
202
+ session_-> opts .timeout = write_timeout_.value_or (kNoTimeout );
203
+ session_-> async_write (req_,
204
+ beast::bind_front_handler (&FoxyClient::on_write,
205
+ shared_from_this ()));
197
206
}
198
207
199
208
void on_write (boost::system::error_code ec, std::size_t amount) {
@@ -205,8 +214,8 @@ class FoxyClient : public Client,
205
214
return do_backoff (ec.what ());
206
215
}
207
216
208
- session_. opts .timeout = read_timeout_.value_or (kNoTimeout );
209
- session_. async_read_header (
217
+ session_-> opts .timeout = read_timeout_.value_or (kNoTimeout );
218
+ session_-> async_read_header (
210
219
*body_parser_, beast::bind_front_handler (&FoxyClient::on_headers,
211
220
shared_from_this ()));
212
221
}
@@ -222,7 +231,7 @@ class FoxyClient : public Client,
222
231
223
232
if (!body_parser_->is_header_done ()) {
224
233
/* keep reading headers */
225
- return session_. async_read_header (
234
+ return session_-> async_read_header (
226
235
*body_parser_,
227
236
beast::bind_front_handler (&FoxyClient::on_headers,
228
237
shared_from_this ()));
@@ -244,7 +253,7 @@ class FoxyClient : public Client,
244
253
backoff_.succeed ();
245
254
246
255
last_read_ = std::chrono::steady_clock::now ();
247
- return session_. async_read_some (
256
+ return session_-> async_read_some (
248
257
*body_parser_,
249
258
beast::bind_front_handler (&FoxyClient::on_read_body,
250
259
shared_from_this ()));
@@ -290,13 +299,13 @@ class FoxyClient : public Client,
290
299
291
300
void on_read_body (boost::system::error_code ec, std::size_t amount) {
292
301
boost::ignore_unused (amount);
293
- if (ec == boost::asio::error::operation_aborted) {
294
- logger_ (" read HTTP response body aborted" );
302
+ if (ec == boost::asio::error::operation_aborted && shutting_down_ ) {
303
+ logger_ (" read HTTP response body aborted (shutting down) " );
295
304
return ;
296
305
}
297
306
if (!ec) {
298
307
log_and_update_last_read (amount);
299
- return session_. async_read_some (
308
+ return session_-> async_read_some (
300
309
*body_parser_,
301
310
beast::bind_front_handler (&FoxyClient::on_read_body,
302
311
shared_from_this ()));
@@ -305,14 +314,16 @@ class FoxyClient : public Client,
305
314
}
306
315
307
316
void async_shutdown (std::function<void ()> completion) override {
308
- boost::asio::post (session_. get_executor (),
317
+ boost::asio::post (session_-> get_executor (),
309
318
beast::bind_front_handler (&FoxyClient::do_shutdown,
310
319
shared_from_this (),
311
320
std::move (completion)));
312
321
}
313
322
314
323
void do_shutdown (std::function<void ()> completion) {
315
- session_.async_shutdown (beast::bind_front_handler (
324
+ shutting_down_ = true ;
325
+ backoff_timer_.cancel ();
326
+ session_->async_shutdown (beast::bind_front_handler (
316
327
&FoxyClient::on_shutdown, std::move (completion)));
317
328
}
318
329
@@ -381,12 +392,14 @@ class FoxyClient : public Client,
381
392
Builder::ErrorCallback errors_;
382
393
383
394
std::optional<http::response_parser<body>> body_parser_;
384
- launchdarkly::foxy::client_session session_;
395
+ std::optional< launchdarkly::foxy::client_session> session_;
385
396
std::optional<std::string> last_event_id_;
386
397
Backoff backoff_;
387
398
boost::asio::steady_timer backoff_timer_;
388
399
389
400
std::optional<std::chrono::steady_clock::time_point> last_read_;
401
+
402
+ bool shutting_down_;
390
403
};
391
404
392
405
Builder::Builder (net::any_io_executor ctx, std::string url)
0 commit comments