Skip to content

Commit bf3b487

Browse files
author
Trading Bot
committed
Fix market data adapter wiring
1 parent 3eca6a7 commit bf3b487

2 files changed

Lines changed: 30 additions & 16 deletions

File tree

src/market_data/health_routes.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,9 @@ async def market_data_admin_discover_subscribe(request: Request) -> Any:
197197
# perform subscribe if requested and adapter available via app.state or module globals
198198
adapter_subscribed = False
199199
try:
200-
adapter = getattr(request.app.state, "market_data_adapter", None)
201-
# fallback to module-level globals if state not set (for tests and legacy compatibility)
202-
if adapter is None:
203-
import webhook_server_fastapi as ws # type: ignore
204-
adapter = getattr(ws, "_market_data_adapter", None)
200+
# Import helper from webhook_server_fastapi
201+
import webhook_server_fastapi as ws # type: ignore
202+
adapter = ws._get_market_data_adapter(request.app)
205203
if adapter is None:
206204
notes.append("adapter_unavailable")
207205
else:

webhook_server_fastapi.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@ def _update_subs_gauge():
133133
_market_data_last_warn_ts: float = 0.0
134134

135135

136+
def _get_market_data_adapter(app=None):
137+
"""Helper to get adapter from app.state or global fallback."""
138+
if app is not None:
139+
adapter = getattr(app.state, "market_data_adapter", None)
140+
if adapter is not None:
141+
return adapter
142+
return _market_data_adapter
143+
144+
136145
async def market_data_event_consumer():
137146
"""
138147
Lightweight consumer that subscribes to the adapter EventBus and processes
@@ -346,7 +355,7 @@ async def _reconcile_once():
346355
logger.exception("Bootstrap reconcile failed")
347356
return {"ok": False, "error": "exception"}
348357
# schedule background reconcile loop
349-
async def reconcile_loop(interval: int = 30):
358+
async def reconcile_loop(app, interval: int = 30):
350359
# Reconcile state with missing-counts to avoid flapping unsubscriptions
351360
from src.market_data.reconcile import ReconcileState, reconcile_step
352361
state = ReconcileState()
@@ -358,6 +367,13 @@ async def reconcile_loop(interval: int = 30):
358367
logger.debug("failed to set module-level reconcile state")
359368
while True:
360369
try:
370+
# Get adapter via helper
371+
adapter = _get_market_data_adapter(app)
372+
if adapter is None:
373+
logger.warning("Reconcile loop: adapter not available, skipping iteration")
374+
await asyncio.sleep(interval)
375+
continue
376+
361377
# Build desired_refcount from open trades
362378
pm = get_position_manager()
363379
active = pm.get_active_trades_summary()
@@ -409,22 +425,22 @@ async def reconcile_loop(interval: int = 30):
409425
# compute actions
410426
try:
411427
missing_threshold = getattr(settings, "MARKET_DATA_RECONCILE_MISSING_THRESHOLD", 3)
412-
res = reconcile_step(_market_data_adapter, desired_refcount, state, missing_threshold=missing_threshold)
428+
res = reconcile_step(adapter, desired_refcount, state, missing_threshold=missing_threshold)
413429
except Exception:
414430
logger.exception("Reconcile step failed")
415431
res = {"to_subscribe": set(), "to_unsubscribe": set()}
416432

417433
# perform subscribe/unsubscribe
418434
for tk in res.get("to_subscribe", set()):
419435
try:
420-
await _market_data_adapter.subscribe(tk)
436+
await adapter.subscribe(tk)
421437
logger.info("Reconcile: requested subscribe %s", str(tk)[:24])
422438
except Exception:
423439
logger.exception("Reconcile: subscribe failed for %s", tk)
424440

425441
for tk in res.get("to_unsubscribe", set()):
426442
try:
427-
await _market_data_adapter.unsubscribe(tk)
443+
await adapter.unsubscribe(tk)
428444
logger.info("Reconcile: requested unsubscribe %s", str(tk)[:24])
429445
state.missing_count.pop(tk, None)
430446
except Exception:
@@ -443,8 +459,8 @@ async def reconcile_loop(interval: int = 30):
443459
except Exception:
444460
last_age = None
445461
dropped = 0
446-
subs_count = len(getattr(_market_data_adapter, "_subs", set())) if _market_data_adapter else 0
447-
logger.info("MarketData reconcile heartbeat: active_subscriptions=%d, last_msg_age_s=%s, ws_connected=%s, dropped_total=%s", subs_count, str(last_age), str(bool(getattr(_market_data_adapter, '_started', False))), str(dropped))
462+
subs_count = len(getattr(adapter, "_subs", set())) if adapter else 0
463+
logger.info("MarketData reconcile heartbeat: active_subscriptions=%d, last_msg_age_s=%s, ws_connected=%s, dropped_total=%s", subs_count, str(last_age), str(bool(getattr(adapter, '_started', False))), str(dropped))
448464
# message-flow verification: if we have subscriptions but no recent messages, warn once per minute
449465
try:
450466
from src.config.settings import get_settings as _get_settings
@@ -458,16 +474,16 @@ async def reconcile_loop(interval: int = 30):
458474
if subs_count > 0 and (last_age is None) and (now_ts - float(getattr(globals(), "_market_data_last_warn_ts", 0.0)) >= 60.0):
459475
example_token = None
460476
try:
461-
example_token = next(iter(getattr(_market_data_adapter, "_subs", set())), None)
477+
example_token = next(iter(getattr(adapter, "_subs", set())), None)
462478
except Exception:
463479
example_token = None
464480
providers = {
465-
"ws": bool(getattr(_market_data_adapter, "provider", None)),
466-
"rtds": bool(getattr(_market_data_adapter, "rtds_provider", None)),
481+
"ws": bool(getattr(adapter, "provider", None)),
482+
"rtds": bool(getattr(adapter, "rtds_provider", None)),
467483
}
468484
logger.warning(
469485
"MarketData warning: no messages received but subscriptions>0; ws_connected=%s subs=%d last_msg_age=%s example_token=%s providers=%s",
470-
str(bool(getattr(_market_data_adapter, "_started", False))),
486+
str(bool(getattr(adapter, "_started", False))),
471487
subs_count,
472488
str(last_age),
473489
str(example_token),
@@ -481,7 +497,7 @@ async def reconcile_loop(interval: int = 30):
481497
except Exception:
482498
logger.exception("Reconcile loop iteration failed")
483499
await asyncio.sleep(interval)
484-
rt = asyncio.create_task(reconcile_loop(interval=getattr(settings, 'MARKET_DATA_RECONCILE_SECONDS', 30)))
500+
rt = asyncio.create_task(reconcile_loop(app, interval=getattr(settings, 'MARKET_DATA_RECONCILE_SECONDS', 30)))
485501
_market_data_tasks.append(rt)
486502
logger.info("MarketData reconcile loop scheduled")
487503
except Exception:

0 commit comments

Comments
 (0)