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:
@@ -49,7 +49,8 @@ int xferCb(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t, curl
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string httpGetString(const std::string& url, const char* logTag)
|
||||
std::string httpGetString(const std::string& url, const char* logTag,
|
||||
long connectTimeoutSec, long timeoutSec)
|
||||
{
|
||||
CURL* curl = curl_easy_init();
|
||||
if (!curl) return {};
|
||||
@@ -59,8 +60,8 @@ std::string httpGetString(const std::string& url, const char* logTag)
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "ObsidianDragon/1.0");
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeoutSec);
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, connectTimeoutSec);
|
||||
curl_easy_setopt(curl, CURLOPT_MAXFILESIZE_LARGE, static_cast<curl_off_t>(kMaxMetadataBytes)); // reject oversized metadata
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
|
||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
|
||||
|
||||
Reference in New Issue
Block a user