Fix positions page hang from blocking CTP IPC and SSE lock wait.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-01 13:33:59 +08:00
parent 5aba31f530
commit 7748a88219
+27 -13
View File
@@ -859,10 +859,17 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
"""关闭无对应 CTP 持仓的监控,并撤销残留止盈止损挂单。""" """关闭无对应 CTP 持仓的监控,并撤销残留止盈止损挂单。"""
return reconcile_monitors_without_position(conn, mode) return reconcile_monitors_without_position(conn, mode)
def _effective_active_position_count(conn, mode: str) -> int: def _effective_active_position_count(
conn,
mode: str,
*,
ctp_connected: Optional[bool] = None,
) -> int:
"""风控持仓数以柜台/快照实际持仓优先,本地监控作兜底。""" """风控持仓数以柜台/快照实际持仓优先,本地监控作兜底。"""
monitor_count = count_active_trade_monitors(conn) monitor_count = count_active_trade_monitors(conn)
if not ctp_status(mode).get("connected"): if ctp_connected is None:
ctp_connected = bool(_cached_ctp_status(mode).get("connected"))
if not ctp_connected:
return monitor_count return monitor_count
keys: set[tuple[str, str]] = set() keys: set[tuple[str, str]] = set()
for p in _positions_for_monitor_restore(mode, allow_ctp=False): for p in _positions_for_monitor_restore(mode, allow_ctp=False):
@@ -2179,15 +2186,10 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
conn.close() conn.close()
if fast: if fast:
if _live_refresh_lock.acquire(blocking=False):
try:
return _build()
finally:
_live_refresh_lock.release()
snap = position_hub.get_snapshot() snap = position_hub.get_snapshot()
if snap: if snap:
return snap return snap
if _live_refresh_lock.acquire(timeout=2.0): if _live_refresh_lock.acquire(blocking=False):
try: try:
return _build() return _build()
finally: finally:
@@ -2415,15 +2417,22 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
try: try:
init_strategy_tables(conn) init_strategy_tables(conn)
mode = get_trading_mode(get_setting) mode = get_trading_mode(get_setting)
ctp_st = ctp_status(mode) ctp_st = _cached_ctp_status(mode)
connected = bool(ctp_st.get("connected"))
capital = _capital(conn) capital = _capital(conn)
recommend_capital = _recommend_capital(conn) recommend_capital = _recommend_capital(conn)
risk = get_risk_status( risk = get_risk_status(
conn, conn,
active_count=_effective_active_position_count(conn, mode), active_count=_effective_active_position_count(
conn, mode, ctp_connected=connected,
),
equity=capital, equity=capital,
) )
ctp_acc = _ctp_account(mode) if ctp_st.get("connected") else {} ctp_acc = {}
bootstrap_live = position_hub.get_snapshot()
if connected and bootstrap_live and bootstrap_live.get("capital") is not None:
cap = float(bootstrap_live.get("capital") or 0)
ctp_acc = {"balance": cap, "available": cap}
active_trend = conn.execute( active_trend = conn.execute(
"SELECT * FROM trend_pullback_plans WHERE status='active' ORDER BY id DESC LIMIT 1" "SELECT * FROM trend_pullback_plans WHERE status='active' ORDER BY id DESC LIMIT 1"
).fetchone() ).fetchone()
@@ -2441,7 +2450,6 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
_schedule_recommend_refresh() _schedule_recommend_refresh()
ctp_connected = is_ctp_connected(get_setting) ctp_connected = is_ctp_connected(get_setting)
margin_rec = small_account_margin_recommendations() margin_rec = small_account_margin_recommendations()
bootstrap_live = position_hub.get_snapshot()
if not bootstrap_live: if not bootstrap_live:
bootstrap_live = { bootstrap_live = {
"ok": True, "ok": True,
@@ -2528,9 +2536,15 @@ def install_trading(app, *, login_required, require_nav, get_db, get_setting, se
if snap: if snap:
yield sse_format("positions", snap) yield sse_format("positions", snap)
else: else:
payload = _refresh_trading_live_snapshot(fast=True) conn = get_db()
try:
init_strategy_tables(conn)
payload = _minimal_live_payload(conn)
finally:
conn.close()
position_hub.set_snapshot(payload) position_hub.set_snapshot(payload)
yield sse_format("positions", payload) yield sse_format("positions", payload)
_push_position_snapshot_async(fast=True)
while True: while True:
try: try:
msg = q.get(timeout=25) msg = q.get(timeout=25)