PINK: fix reconcile 30s deadlock — async def + direct await
Root cause: _run() → pool.submit(asyncio.run, coro).result(30s) created a new event loop in a thread-pool thread; aiohttp session is main-loop-bound → silent deadlock every step cycle. BingX VST is healthy (544ms gather). Fix: async def reconcile() + await self.backend.refresh_state() in main loop. pump_venue_events() already handles isawaitable → zero caller changes. include_history=False (symbol=None skips history anyway). Tests: 13/13 passing (async contract, 3 fault paths, <2s timing, gather-10). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -393,8 +393,30 @@ class BingxVenueAdapter(VenueAdapter):
|
||||
snapshot = self._backend_snapshot(include_history=False)
|
||||
return [dict(row) for row in (snapshot.open_positions or {}).values()]
|
||||
|
||||
def reconcile(self) -> List[VenueEvent]:
|
||||
snapshot = self._backend_snapshot(include_history=True)
|
||||
async def reconcile(self) -> List[VenueEvent]: # type: ignore[override]
|
||||
"""Fetch open-order state from BingX and return any pending VenueEvents.
|
||||
|
||||
WHY ASYNC: the old sync version called _backend_snapshot() → _call_backend()
|
||||
→ _run() → pool.submit(asyncio.run, coro).result(timeout=30s). That spawned
|
||||
a *new* event loop in a thread-pool thread. The BingxHttpClient (aiohttp
|
||||
session) is bound to the *main* event loop — using it from a different loop
|
||||
silently deadlocks. BingX VST responds in ~500ms; the deadlock made every
|
||||
reconcile call block the main event loop for the full 30s timeout.
|
||||
|
||||
FIX: declare async, call backend.refresh_state() directly with await so it
|
||||
runs in the *caller's* (main) event loop where the session lives.
|
||||
pump_venue_events() already has `if inspect.isawaitable(events): await events`
|
||||
— zero caller changes required.
|
||||
|
||||
include_history=False: all_orders/all_fills require a symbol (symbol=None
|
||||
skips them anyway), so include_history=True was fetching nothing extra.
|
||||
"""
|
||||
try:
|
||||
snapshot = await self.backend.refresh_state(None, include_history=False)
|
||||
except Exception as exc:
|
||||
import logging as _log
|
||||
_log.getLogger(__name__).warning("reconcile: refresh_state failed: %s", exc)
|
||||
return []
|
||||
return self._events_from_snapshot(snapshot)
|
||||
|
||||
def submit(self, intent: KernelIntent) -> List[VenueEvent]:
|
||||
|
||||
Reference in New Issue
Block a user