fix: broadcast active cluster em todo tick live, heartbeat WS

Remove guard closed_json que bloqueava updates do cluster ativo.
Frontend recebe estado a cada tick sem precisar de F5.
Heartbeat ping a cada 20s para manter conexao WS viva.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
rufinomec-afk
2026-06-07 23:06:57 -03:00
co-authored by Claude Sonnet 4.6
parent 6fe8920412
commit 310c1f52bd
+16 -5
View File
@@ -25,11 +25,11 @@ collector_task: Optional[asyncio.Task] = None
def broadcast_update(active_json: dict, closed_json: Optional[dict]): def broadcast_update(active_json: dict, closed_json: Optional[dict]):
""" """
Callback executed by MT5Collector when a new tick is processed. Callback executed by MT5Collector on every live tick.
Only broadcasts when a cluster closes (not every tick) to avoid flooding during replay. Always broadcasts the active cluster state so the frontend updates in real-time.
Removes dead connections automatically. closed_json is None between cluster closes — frontend handles that gracefully.
""" """
if not active_connections or closed_json is None: if not active_connections:
return return
message = { message = {
"type": "tick", "type": "tick",
@@ -124,7 +124,6 @@ async def websocket_endpoint(websocket: WebSocket):
active_connections.add(websocket) active_connections.add(websocket)
logger.info(f"Client connected. Active connections: {len(active_connections)}") logger.info(f"Client connected. Active connections: {len(active_connections)}")
# Send the current active cluster state on connection
try: try:
await websocket.send_json({ await websocket.send_json({
"type": "init", "type": "init",
@@ -133,6 +132,16 @@ async def websocket_endpoint(websocket: WebSocket):
except Exception as e: except Exception as e:
logger.error(f"Error sending init state: {e}") logger.error(f"Error sending init state: {e}")
async def heartbeat():
"""Ping every 20s to keep the connection alive through proxies/browsers."""
try:
while True:
await asyncio.sleep(20)
await websocket.send_json({"type": "ping"})
except Exception:
pass
ping_task = asyncio.create_task(heartbeat())
try: try:
while True: while True:
await websocket.receive_text() await websocket.receive_text()
@@ -142,6 +151,8 @@ async def websocket_endpoint(websocket: WebSocket):
except Exception as e: except Exception as e:
logger.error(f"WebSocket error: {e}") logger.error(f"WebSocket error: {e}")
active_connections.discard(websocket) active_connections.discard(websocket)
finally:
ping_task.cancel()
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn