From f086f57c918f1d89b7813c58767c63539ddd5b91 Mon Sep 17 00:00:00 2001 From: dekun Date: Tue, 11 Aug 2026 12:38:25 +0800 Subject: [PATCH] fix(gate): never block hub account on live balance fetch Under RS alert ccxt contention, sync get_exchange_capitals made /api/hub/account time out. Return cache immediately and refresh in a background thread when force=False. Co-authored-by: Cursor --- crypto_monitor_gate/app.py | 49 +++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/crypto_monitor_gate/app.py b/crypto_monitor_gate/app.py index a37848c..cdfe660 100644 --- a/crypto_monitor_gate/app.py +++ b/crypto_monitor_gate/app.py @@ -2834,13 +2834,13 @@ def friendly_exchange_error(err, available_usdt=None): return f"交易所下单失败:{clean}" -def get_exchange_capitals(force=False): - ok_live, _ = ensure_exchange_live_ready() - if not ok_live: - return None, None +_BALANCE_REFRESH_LOCK = threading.Lock() +_BALANCE_REFRESH_INFLIGHT = False + + +def _fetch_exchange_capitals_sync(): + """同步拉取资金/交易账户余额并写入缓存(会占用 ccxt,勿在中控热路径直接调用).""" now_ts = time.time() - if (not force) and ACCOUNT_BALANCE_CACHE["updated_at"] and now_ts - ACCOUNT_BALANCE_CACHE["updated_at"] < BALANCE_REFRESH_SECONDS: - return ACCOUNT_BALANCE_CACHE["funding_usdt"], ACCOUNT_BALANCE_CACHE["trading_usdt"] try: ACCOUNT_BALANCE_CACHE["funding_usdt"] = _fetch_gate_funding_usdt() except Exception: @@ -2854,6 +2854,43 @@ def get_exchange_capitals(force=False): return ACCOUNT_BALANCE_CACHE["funding_usdt"], ACCOUNT_BALANCE_CACHE["trading_usdt"] +def _kick_exchange_capitals_refresh(): + """后台刷新余额;与 key_rs 争用时不阻塞看板/中控请求.""" + global _BALANCE_REFRESH_INFLIGHT + with _BALANCE_REFRESH_LOCK: + if _BALANCE_REFRESH_INFLIGHT: + return + _BALANCE_REFRESH_INFLIGHT = True + + def _worker(): + global _BALANCE_REFRESH_INFLIGHT + try: + _fetch_exchange_capitals_sync() + except Exception: + pass + finally: + with _BALANCE_REFRESH_LOCK: + _BALANCE_REFRESH_INFLIGHT = False + + threading.Thread(target=_worker, name="gate-balance-refresh", daemon=True).start() + + +def get_exchange_capitals(force=False): + ok_live, _ = ensure_exchange_live_ready() + if not ok_live: + return None, None + now_ts = time.time() + has_cache = bool(ACCOUNT_BALANCE_CACHE["updated_at"]) + fresh = has_cache and (now_ts - ACCOUNT_BALANCE_CACHE["updated_at"] < BALANCE_REFRESH_SECONDS) + if (not force) and fresh: + return ACCOUNT_BALANCE_CACHE["funding_usdt"], ACCOUNT_BALANCE_CACHE["trading_usdt"] + if not force: + # 过期/冷缓存:先返回现有值(可空),后台刷新,避免 /api/hub/account 被 RS 监控拖死 + _kick_exchange_capitals_refresh() + return ACCOUNT_BALANCE_CACHE["funding_usdt"], ACCOUNT_BALANCE_CACHE["trading_usdt"] + return _fetch_exchange_capitals_sync() + + def execute_transfer_usdt(amount, from_account, to_account): from lib.exchange.gate_transfer_lib import execute_transfer_usdt as _gate_execute_transfer_usdt