mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-09-30 12:42:26 +07:00
Enforce a minimum SSE reconnect wait to avoid a busy loop (#2592)
SSEClient::wait_for_reconnect() sleeps in 100ms steps until the reconnect interval has elapsed. With an interval of 0 (for example "retry: 0" from the server, or set_reconnect_interval(0)) it never slept at all, so a server that sends "retry: 0" and closes the stream made the client reconnect in a tight loop. set_max_reconnect_attempts() does not stop this either, because each successful connection resets the attempt counter. Always wait at least one step (100ms). Intervals of 1-99ms already waited 100ms because of the step size, so only 0 and negative values change behavior.
This commit is contained in:
+1
-1
@@ -69,7 +69,7 @@ sse.on_error([](httplib::Error err) { });
|
|||||||
#### Configuration
|
#### Configuration
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
// Set reconnect interval (default: 3000ms)
|
// Set reconnect interval (default: 3000ms, minimum: 100ms)
|
||||||
sse.set_reconnect_interval(5000);
|
sse.set_reconnect_interval(5000);
|
||||||
|
|
||||||
// Set max reconnect attempts (default: 0 = unlimited)
|
// Set max reconnect attempts (default: 0 = unlimited)
|
||||||
|
|||||||
@@ -5051,11 +5051,15 @@ inline bool SSEClient::should_reconnect(int count) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void SSEClient::wait_for_reconnect() {
|
inline void SSEClient::wait_for_reconnect() {
|
||||||
// Use small increments to check running_ flag frequently
|
// Use small increments to check running_ flag frequently.
|
||||||
|
// Always wait at least one increment, so that a zero interval (e.g.
|
||||||
|
// "retry: 0" from the server) cannot cause a busy reconnect loop.
|
||||||
|
const auto step_ms = 100;
|
||||||
|
auto interval_ms = (std::max)(reconnect_interval_ms_, step_ms);
|
||||||
auto waited = 0;
|
auto waited = 0;
|
||||||
while (running_.load() && waited < reconnect_interval_ms_) {
|
while (running_.load() && waited < interval_ms) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(step_ms));
|
||||||
waited += 100;
|
waited += step_ms;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22702,7 +22702,10 @@ TEST_F(SSEIntegrationTest, DigitRetryFieldApplied) {
|
|||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
sse.stop();
|
sse.stop();
|
||||||
|
|
||||||
|
// The server-supplied interval is applied, but never below 100ms, so
|
||||||
|
// "retry: 0" does not cause a busy reconnect loop
|
||||||
EXPECT_GE(connection_count.load(), 2);
|
EXPECT_GE(connection_count.load(), 2);
|
||||||
|
EXPECT_LE(connection_count.load(), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test: Last-Event-ID sent on reconnect
|
// Test: Last-Event-ID sent on reconnect
|
||||||
|
|||||||
Reference in New Issue
Block a user