feat: Integrate WebSocket Gateway into API-based task launch

- Gateway now starts automatically when calling POST /runtime/start
- No need to run python backend/main.py separately
- Single service architecture: only FastAPI (port 8000) needed
- Gateway runs in background task and stops with pipeline
- Add error handling and logging for Gateway lifecycle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-17 18:36:33 +08:00
parent a3f767126f
commit 2dcda63394
2 changed files with 111 additions and 22 deletions

View File

@@ -238,30 +238,45 @@ class Gateway:
self.connected_clients.discard(websocket)
async def _send_initial_state(self, websocket: ServerConnection):
state_payload = self.state_sync.get_initial_state_payload(
include_dashboard=True,
)
state_payload["data_sources"] = (
self._provider_router.get_usage_snapshot()
)
# Include market status in initial state
state_payload[
"market_status"
] = self.market_service.get_market_status()
try:
logger.info("[Gateway] Sending initial state to client...")
state_payload = self.state_sync.get_initial_state_payload(
include_dashboard=True,
)
state_payload["data_sources"] = (
self._provider_router.get_usage_snapshot()
)
# Include market status in initial state
state_payload[
"market_status"
] = self.market_service.get_market_status()
# Include live returns if session is active
if self.storage.is_live_session_active:
live_returns = self.storage.get_live_returns()
if "portfolio" in state_payload:
state_payload["portfolio"].update(live_returns)
# Include live returns if session is active
if self.storage.is_live_session_active:
live_returns = self.storage.get_live_returns()
if "portfolio" in state_payload:
state_payload["portfolio"].update(live_returns)
await websocket.send(
json.dumps(
{"type": "initial_state", "state": state_payload},
ensure_ascii=False,
default=str,
),
)
await websocket.send(
json.dumps(
{"type": "initial_state", "state": state_payload},
ensure_ascii=False,
default=str,
),
)
logger.info("[Gateway] Initial state sent successfully")
except Exception as e:
logger.exception(f"[Gateway] Failed to send initial state: {e}")
# Send error response so client knows something went wrong
try:
await websocket.send(
json.dumps(
{"type": "error", "message": "Failed to load initial state"},
ensure_ascii=False,
),
)
except Exception:
pass
async def _handle_client_messages(
self,