Compare commits

...

1 Commits

Author SHA1 Message Date
Nicholas Dudfield
d18c1004f6 fix(server): preserve idle JSON-RPC keep-alives 2026-09-01 09:46:24 +07:00
2 changed files with 28 additions and 1 deletions

View File

@@ -300,7 +300,13 @@ BaseHTTPPeer<Handler, Impl>::do_read(yield_context do_yield)
{
complete_ = false;
error_code ec;
start_timer();
// Do not treat an established keep-alive waiting for its next request as
// an unfinished loopback request.
if (request_count_ == 0)
start_timer();
else
boost::beast::get_lowest_layer(impl().stream_)
.expires_after(std::chrono::seconds(timeoutSeconds));
boost::beast::http::async_read(
impl().stream_, read_buf_, message_, do_yield[ec]);
cancel_timer();

View File

@@ -28,7 +28,9 @@
#include <xrpl/protocol/jss.h>
#include <boost/lexical_cast.hpp>
#include <chrono>
#include <optional>
#include <thread>
#include <utility>
namespace ripple {
@@ -906,6 +908,24 @@ public:
pass();
}
void
testJSONRPCClientKeepAlive()
{
testcase("JSON-RPC keep-alive survives test work");
using namespace std::chrono_literals;
using namespace jtx;
Env env{*this};
env.client().invoke("server_info", {});
// The normal loopback message timeout is three seconds. Established
// Env connections have a separate idle lease because test work can
// legitimately take longer between RPCs.
std::this_thread::sleep_for(4s);
auto const response = env.client().invoke("server_info", {});
BEAST_EXPECT(response[jss::result][jss::status] == "success");
}
void
run() override
{
@@ -933,6 +953,7 @@ public:
testSignAndSubmit(all);
testFeatures(all);
testExceptionalShutdown();
testJSONRPCClientKeepAlive();
}
};