fix(node): fail the localhost connect probe fast (8s, not 30s)

The connection probe (getinfo) used a 30s request timeout, so when something on
the local RPC port accepts TCP but never answers — a daemon still loading the
block index, or a wedged/foreign occupant — every attempt blocked the full 30s
before the wallet could retry or update its status. That is the "stuck, timing
out every 30s" behaviour users hit.

A healthy local daemon answers getinfo in milliseconds, and a warming one
returns -28 just as fast, so a long hang on localhost only ever means trouble.
Probe localhost with an 8s timeout (remote/TLS keeps the 30s budget). The
per-call override restores the persistent 30s afterwards, so normal RPC calls
that legitimately take longer are unaffected — only the probe fails faster, so
the wallet retries promptly and reflects "initializing" / recovery within
seconds of the daemon becoming ready.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 21:25:22 -05:00
parent 2ba8a799ff
commit 1fb6dc44d9

View File

@@ -189,9 +189,14 @@ bool RPCClient::connect(const std::string& host, const std::string& port,
const long connectTimeout = Connection::isLocalHost(host) ? 2L : 10L; const long connectTimeout = Connection::isLocalHost(host) ? 2L : 10L;
curl_easy_setopt(impl_->curl, CURLOPT_CONNECTTIMEOUT, connectTimeout); curl_easy_setopt(impl_->curl, CURLOPT_CONNECTTIMEOUT, connectTimeout);
// Test connection with getinfo // Test connection with getinfo. Use a SHORT timeout for the probe on localhost: a healthy
// local daemon answers in milliseconds and a warming one returns -28 just as fast, so a long
// hang means a wedged/loading occupant — no point blocking the full 30s before we retry and
// update the UI. (call(timeoutSec) restores the persistent 30s afterwards, so normal RPC calls
// that legitimately take longer are unaffected.) Remote/TLS daemons keep the full budget.
const long probeTimeout = Connection::isLocalHost(host) ? 8L : 30L;
try { try {
json result = call("getinfo"); json result = call("getinfo", json::array(), probeTimeout);
if (result.contains("version")) { if (result.contains("version")) {
connected_ = true; connected_ = true;
warming_up_ = false; warming_up_ = false;