fix(lite): fast retry when a server is only warming up (-28)
When the preferred lightwalletd server is reachable but warming up (JSON-RPC -28 / "Activating best chain"), the failover treated it like a dead server and fell through to the others, so the wallet didn't open until the next 20s retry — even though the healthy server was ready within seconds. Detect the warmup error during failover, flag it on the open outcome (lastOpenWasWarmup()), and have the App retry on a short ~4s interval in that case instead of 20s, so the wallet opens promptly once warmup clears. A unit test covers a warming-preferred + dead-fallback open setting the flag. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,16 @@ namespace wallet {
|
||||
namespace {
|
||||
constexpr double kZatoshisPerCoin = 100000000.0; // DRGX has 1e8 zatoshis per coin
|
||||
|
||||
// A lightwalletd open error that means "server is up but still warming up" (JSON-RPC -28 /
|
||||
// "Activating best chain", "Loading"/"Verifying"/"Rescanning" phases) rather than a dead server.
|
||||
// Such a server will be ready shortly, so the caller should retry it soon.
|
||||
bool liteOpenErrorIsWarmup(const std::string& error)
|
||||
{
|
||||
const auto has = [&error](const char* s) { return error.find(s) != std::string::npos; };
|
||||
return has("-28") || has("Activating best chain") || has("warming up") ||
|
||||
has("Loading block") || has("Verifying blocks") || has("Rescanning");
|
||||
}
|
||||
|
||||
// Extract a backend {"error":..} message (string or arbitrary JSON) into a plain string.
|
||||
std::string extractJsonError(const nlohmann::json& value)
|
||||
{
|
||||
@@ -361,7 +371,10 @@ bool LiteWalletController::beginOpenExisting()
|
||||
}
|
||||
const std::string why = call.error.empty() ? "unreachable" : call.error;
|
||||
liteLog(" " + url + ": " + why);
|
||||
if (!call.error.empty()) outcome.error = call.error;
|
||||
if (!call.error.empty()) {
|
||||
outcome.error = call.error;
|
||||
if (liteOpenErrorIsWarmup(call.error)) outcome.warming = true; // healthy, just starting
|
||||
}
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(*resultMutex);
|
||||
@@ -386,6 +399,7 @@ void LiteWalletController::pumpAsyncOpen()
|
||||
if (outcome.ok) {
|
||||
walletOpen_ = true;
|
||||
lastOpenError_.clear();
|
||||
lastOpenWarming_ = false;
|
||||
status_ = WalletBackendStatus{WalletBackendState::Ready, "wallet open", {}, {}, 0.0};
|
||||
liteLog("Wallet opened via " + outcome.serverUrl);
|
||||
if (persist_) persist_();
|
||||
@@ -393,8 +407,10 @@ void LiteWalletController::pumpAsyncOpen()
|
||||
startWorker(); // begin periodic refresh -> WalletState
|
||||
} else {
|
||||
lastOpenError_ = outcome.error;
|
||||
lastOpenWarming_ = outcome.warming; // a healthy server was warming up -> retry sooner
|
||||
status_ = WalletBackendStatus{WalletBackendState::Error, outcome.error, {}, {}, 0.0};
|
||||
liteLog("Open failed: " + outcome.error);
|
||||
liteLog("Open failed: " + outcome.error +
|
||||
(outcome.warming ? " (a server is warming up — will retry shortly)" : ""));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user