fix(rescan): detect this daemon's completion ("rescan <N>ms"), unstick 99%

A rescan ran to completion but the status bar stayed at "Rescanning 99%"
forever. The daemon-output parser only treated "Done rescanning"/"Rescan
complete" as finished, but this daemon prints neither — it logs the rescan
benchmark timing line exactly when the scan ends:

    2026-... rescan             16760577ms

then resumes normal block processing. So the parser saw the last
"Still rescanning ... Progress=0.99" and never the finish, leaving it stuck.

- Recognise the " rescan <N>ms" bench line as completion (it ends in "ms",
  which the "Still rescanning"/"Rescanning..." progress lines never do).
- When the parser reads "Still rescanning" straight from the daemon log, mark
  rescan_confirmed_active_ — hard proof the scan is running that doesn't depend
  on catching a getrescaninfo warmup error, so the RPC completion path can also
  fire after the daemon leaves warmup. Clear it on finish.

The parser reads the daemon's debug.log via the controller (not RPC), so this
completes the rescan UI even if the RPC connection hasn't re-established yet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-13 08:16:25 -05:00
parent b9b2d469d4
commit 3a597482da

View File

@@ -752,6 +752,21 @@ void App::update()
line.find("Rescan complete") != std::string::npos) {
finished = true;
}
// This daemon prints no "Done rescanning" line; instead it logs the rescan
// benchmark timing exactly when the scan finishes, e.g.:
// "... rescan 16760577ms"
// Match the lowercase " rescan " bench category ending in "<digits>ms" (the
// progress lines are "Still rescanning"/"Rescanning...", which never end in ms).
if (line.find(" rescan ") != std::string::npos) {
std::string t = line;
while (!t.empty() && (t.back() == '\r' || t.back() == '\n' || t.back() == ' '))
t.pop_back();
if (t.size() >= 3 && t.compare(t.size() - 2, 2, "ms") == 0 &&
std::isdigit(static_cast<unsigned char>(t[t.size() - 3]))) {
finished = true;
}
}
}
// Return callback to apply results on main thread
@@ -761,10 +776,15 @@ void App::update()
ui::Notifications::instance().success("Blockchain rescan complete");
}
state_.sync.rescanning = false;
rescan_confirmed_active_ = false;
state_.sync.rescan_progress = 1.0f;
state_.sync.rescan_status.clear();
} else if (foundRescan) {
state_.sync.rescanning = true;
// Reading "Still rescanning" straight from the daemon log is hard proof the
// rescan is genuinely running — confirm it so the getrescaninfo poll's
// completion check can fire even if it never caught a warmup error.
rescan_confirmed_active_ = true;
if (rescanPct > 0.0f) {
state_.sync.rescan_progress = rescanPct / 100.0f;
}