fix(market): back off failed market fetches instead of retrying every frame
The Market tab calls the exchange-list, price-history and candle fetches every frame, so a failed fetch (offline, rate-limited, a venue's API down) was retried on the very next frame, ~20 requests a second. - util::FetchBackoff: 30 s doubling to a 10 min cap, +/-20% jitter. The exchange list, the price history (a partial result counts as a failure) and the per-pair candles each back off on failure. - Candle backoff is per pair. Switching to another pair still loads at once, a failed refresh keeps the on-screen pair's last candles, and switching back to a pair that is backing off shows the aggregate chart rather than the previous pair's candles. - The Market tab's refresh button retries at once (at most every 5 s). A price fetch (60 s timer, no backoff) that succeeds after failing means the network is back, so it lifts all three backoffs. - A partial price history no longer marks the chart loaded: with no fetch timestamp, the 30-minute reload gate measured system uptime and blocked retries for the first 30 minutes after boot. - The exchange list goes through httpGetString (TLS verified, size capped) with short timeouts (5 s connect, 12 s total, as it runs on the shared RPC worker) instead of its own curl code. A failed fetch is retried; it used to be tried only once per session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include "services/wallet_security_controller.h"
|
||||
#include "services/wallet_security_workflow.h"
|
||||
#include "util/async_task_manager.h"
|
||||
#include "util/fetch_backoff.h"
|
||||
#include "util/pool_stats_service.h"
|
||||
#include "wallet/wallet_capabilities.h"
|
||||
#include "chat/chat_service.h"
|
||||
@@ -441,6 +442,9 @@ public:
|
||||
void refreshMiningInfo();
|
||||
void refreshPeerInfo();
|
||||
void refreshMarketData();
|
||||
// The Market tab's refresh button: lift any failure backoff (at most once per 5 s, against click
|
||||
// spam), then refreshMarketData().
|
||||
void retryMarketDataNow();
|
||||
// Fetch the live exchange/pair list from CoinGecko once per session (venues are
|
||||
// near-static); populates state.market.exchanges. Safe to call every frame.
|
||||
void refreshExchanges();
|
||||
@@ -984,8 +988,16 @@ private:
|
||||
long long last_balance_eval_ms_ = 0; // steady-clock ms of the last refresh kick
|
||||
bool balance_refresh_pending_ = false; // UI asked for an immediate refresh
|
||||
bool balance_snapshot_seen_ = false; // the current in-flight snapshot was applied
|
||||
bool exchanges_fetch_started_ = false; // once-per-session CoinGecko tickers fetch
|
||||
bool exchanges_fetch_started_ = false; // CoinGecko tickers fetch in flight or done (once per session)
|
||||
bool chart_fetch_in_flight_ = false; // a market_chart history fetch is on the worker
|
||||
// Failed market fetches back off instead of retrying: the Market tab calls these every frame, so a
|
||||
// failure (offline, rate-limited) used to retry on the very next frame, ~20 requests a second.
|
||||
util::FetchBackoff exchanges_backoff_;
|
||||
util::FetchBackoff market_chart_backoff_;
|
||||
util::FetchBackoff exchange_chart_backoff_; // for exchange_chart_fail_key_ only: other pairs still load
|
||||
std::string exchange_chart_fail_key_;
|
||||
std::chrono::steady_clock::time_point market_manual_retry_at_{};
|
||||
bool price_fetch_failed_ = false; // last price fetch failed (connectivity probe for the backoffs)
|
||||
// Per-exchange candle chart (refreshExchangeChart): which pair the loaded series is for, an
|
||||
// in-flight guard, and a slow refresh timer (candles move slowly, like the aggregate chart).
|
||||
std::string exchange_chart_key_; // "<identifier>:<BASE>/<QUOTE>" of the loaded series ("" = none)
|
||||
|
||||
Reference in New Issue
Block a user