feat(mining): persistent start/stop error caption + timeout-aware pool status
- A mining start/stop/pool failure now sets a persistent App::mining_last_error_ (cleared on the next attempt), rendered as a red caption with "Press Mine to try again" below the Mine button (plus a Dismiss, and a Windows-Defender "How to fix" on an AV block), so a crashed/blocked/failed miner is no longer just a button that "did nothing" once its toast faded. Two more hardcoded English strings (pool-payout-invalid, AV-blocked) moved to i18n. - Pool connection status is now a persistent "Status" row in the pool stats card (PoolMiningState.running_since / last_error): it flips from "Connecting…" to "Can't reach pool — check the URL" after a 30s timeout instead of sitting on red forever, and no longer vanishes once logs arrive. The old transient banner in mining_tab.cpp was removed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+21
-2
@@ -1233,14 +1233,18 @@ void App::update()
|
||||
if (xmrig_manager_ && state_.pool_mining.xmrig_running
|
||||
&& xmrig_manager_->getState() == daemon::XmrigManager::State::Error) {
|
||||
state_.pool_mining.xmrig_running = false;
|
||||
state_.pool_mining.running_since = 0;
|
||||
state_.pool_mining.last_error.clear();
|
||||
state_.pool_mining.hashrate_10s = 0.0;
|
||||
state_.pool_mining.hashrate_60s = 0.0;
|
||||
state_.pool_mining.hashrate_15m = 0.0;
|
||||
pool_starting_.store(false, std::memory_order_relaxed);
|
||||
pool_threads_target_.store(0, std::memory_order_relaxed); // that miner is gone
|
||||
const std::string err = xmrig_manager_->getLastError();
|
||||
ui::Notifications::instance().error(err.empty() ? TR("appx_miner_stopped_unexpectedly")
|
||||
: (std::string(TR("appx_miner_stopped_prefix")) + err));
|
||||
const std::string mmsg = err.empty() ? std::string(TR("appx_miner_stopped_unexpectedly"))
|
||||
: (std::string(TR("appx_miner_stopped_prefix")) + err);
|
||||
setMiningError(mmsg); // persist: a miner that crashed/was killed otherwise just "did nothing"
|
||||
ui::Notifications::instance().error(mmsg);
|
||||
}
|
||||
|
||||
// Poll xmrig stats every ~2 seconds (use a simple toggle)
|
||||
@@ -1273,6 +1277,19 @@ void App::update()
|
||||
ps.threads_active = xs.threads_active;
|
||||
ps.pool_hashrate = xs.pool_hashrate;
|
||||
ps.log_lines = xmrig_manager_->getRecentLines(30);
|
||||
if (ps.running_since == 0) ps.running_since = std::time(nullptr);
|
||||
// While not yet connected, surface the newest error-looking log line so "Connecting" can flip
|
||||
// to a real "can't reach pool" after a timeout instead of sitting on red forever.
|
||||
ps.last_error.clear();
|
||||
if (!ps.connected) {
|
||||
for (auto it = ps.log_lines.rbegin(); it != ps.log_lines.rend(); ++it) {
|
||||
std::string l = *it;
|
||||
std::transform(l.begin(), l.end(), l.begin(), [](unsigned char c){ return (char)std::tolower(c); });
|
||||
if (l.find("error") != std::string::npos || l.find("refused") != std::string::npos ||
|
||||
l.find("timed out") != std::string::npos || l.find("unreachable") != std::string::npos ||
|
||||
l.find("dns") != std::string::npos) { ps.last_error = *it; break; }
|
||||
}
|
||||
}
|
||||
|
||||
// Record hashrate sample for the chart
|
||||
ps.hashrate_history.push_back(ps.hashrate_10s);
|
||||
@@ -1283,6 +1300,8 @@ void App::update()
|
||||
}
|
||||
} else if (xmrig_manager_ && !xmrig_manager_->isRunning()) {
|
||||
state_.pool_mining.xmrig_running = false;
|
||||
state_.pool_mining.running_since = 0;
|
||||
state_.pool_mining.last_error.clear();
|
||||
pool_starting_.store(false, std::memory_order_relaxed); // stopped / never came up
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user