mgbam commited on
Commit
3b67fa5
Β·
verified Β·
1 Parent(s): 9c7fae0

Update app/app.py

Browse files
Files changed (1) hide show
  1. app/app.py +17 -12
app/app.py CHANGED
@@ -9,6 +9,7 @@ import asyncio
9
  import os
10
  import json
11
  import time
 
12
  from datetime import datetime, timezone
13
 
14
  import httpx
@@ -16,20 +17,16 @@ import socketio
16
  from fastapi import FastAPI
17
  from fastapi.staticfiles import StaticFiles
18
 
 
19
  from .price_fetcher import PriceFetcher
20
  from .arbitrage_analyzer import ArbitrageAnalyzer
21
 
22
  OPPORTUNITY_THRESHOLD = 0.0015
23
 
24
  # --- Socket.IO Server Setup ---
25
- # We create the server instance that will manage all real-time communication.
26
  sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins='*')
27
 
28
- # --- FastAPI App Setup ---
29
- # The FastAPI app is now simpler. It only serves the static files.
30
- app = FastAPI()
31
- app.mount("/", StaticFiles(directory="static", html=True), name="static")
32
-
33
  # --- Background Engine ---
34
  async def run_arbitrage_detector(price_fetcher, analyzer):
35
  """The core engine loop. Detects opportunities and emits them via Socket.IO."""
@@ -59,6 +56,7 @@ async def run_arbitrage_detector(price_fetcher, analyzer):
59
  briefing = await analyzer.get_alpha_briefing(asset, opportunity)
60
  if briefing:
61
  signal = {**opportunity, **briefing, "timestamp": datetime.now(timezone.utc).isoformat()}
 
62
  await sio.emit('new_signal', signal)
63
  print(f"βœ… Signal Emitted for {asset}: {signal['strategy']}")
64
  except Exception as e:
@@ -67,12 +65,13 @@ async def run_arbitrage_detector(price_fetcher, analyzer):
67
  await asyncio.sleep(15)
68
 
69
  # --- Socket.IO Lifespan Events ---
70
- # This is the CORRECT way to manage background tasks with python-socketio.
71
  @sio.on('connect')
72
  async def connect(sid, environ):
 
73
  print(f"βœ… Client connected: {sid}")
74
  # Start the engine only when the first user connects.
75
- if sio.background_task is None:
76
  print("πŸš€ First client connected. Starting Sentinel Engine...")
77
  price_fetcher = PriceFetcher(httpx.AsyncClient())
78
  arbitrage_analyzer = ArbitrageAnalyzer(httpx.AsyncClient())
@@ -82,9 +81,15 @@ async def connect(sid, environ):
82
 
83
  @sio.on('disconnect')
84
  def disconnect(sid):
 
85
  print(f"πŸ”₯ Client disconnected: {sid}")
86
 
87
- # --- Final ASGI App ---
88
- # We wrap the FastAPI app (for static files) and the Socket.IO app together.
89
- # The Socket.IO server is the primary application.
90
- combined_app = socketio.ASGIApp(sio, other_asgi_app=app)
 
 
 
 
 
 
9
  import os
10
  import json
11
  import time
12
+ from contextlib import asynccontextmanager
13
  from datetime import datetime, timezone
14
 
15
  import httpx
 
17
  from fastapi import FastAPI
18
  from fastapi.staticfiles import StaticFiles
19
 
20
+ # Relative imports for our package structure
21
  from .price_fetcher import PriceFetcher
22
  from .arbitrage_analyzer import ArbitrageAnalyzer
23
 
24
  OPPORTUNITY_THRESHOLD = 0.0015
25
 
26
  # --- Socket.IO Server Setup ---
27
+ # This creates the server instance that will handle all real-time communication.
28
  sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins='*')
29
 
 
 
 
 
 
30
  # --- Background Engine ---
31
  async def run_arbitrage_detector(price_fetcher, analyzer):
32
  """The core engine loop. Detects opportunities and emits them via Socket.IO."""
 
56
  briefing = await analyzer.get_alpha_briefing(asset, opportunity)
57
  if briefing:
58
  signal = {**opportunity, **briefing, "timestamp": datetime.now(timezone.utc).isoformat()}
59
+ # Directly emit to all connected clients
60
  await sio.emit('new_signal', signal)
61
  print(f"βœ… Signal Emitted for {asset}: {signal['strategy']}")
62
  except Exception as e:
 
65
  await asyncio.sleep(15)
66
 
67
  # --- Socket.IO Lifespan Events ---
68
+ # This is the correct way to manage background tasks with python-socketio.
69
  @sio.on('connect')
70
  async def connect(sid, environ):
71
+ """Handles new client connections."""
72
  print(f"βœ… Client connected: {sid}")
73
  # Start the engine only when the first user connects.
74
+ if not hasattr(sio, 'background_task') or sio.background_task.done():
75
  print("πŸš€ First client connected. Starting Sentinel Engine...")
76
  price_fetcher = PriceFetcher(httpx.AsyncClient())
77
  arbitrage_analyzer = ArbitrageAnalyzer(httpx.AsyncClient())
 
81
 
82
  @sio.on('disconnect')
83
  def disconnect(sid):
84
+ """Handles client disconnections."""
85
  print(f"πŸ”₯ Client disconnected: {sid}")
86
 
87
+
88
+ # --- FastAPI App & Final ASGI App ---
89
+ # Create a minimal FastAPI app just to serve the static files.
90
+ fastapi_app = FastAPI()
91
+ fastapi_app.mount("/", StaticFiles(directory="static", html=True), name="static")
92
+
93
+ # Wrap the FastAPI app (for static files) with the Socket.IO app.
94
+ # The Socket.IO server is the primary application that handles requests.
95
+ combined_app = socketio.ASGIApp(sio, other_asgi_app=fastapi_app)