abinazebinoy commited on
Commit
e95e7d1
·
1 Parent(s): 13839a7

fix(BUG-01/06/24): WebSocket now pushes heartbeat every 15s; /stats uses single session

Browse files
Files changed (1) hide show
  1. api/main.py +34 -20
api/main.py CHANGED
@@ -111,28 +111,26 @@ def get_stats():
111
  driver = get_driver()
112
  node_counts = {}
113
  rel_counts = {}
114
- if driver:
115
- with driver.session() as session:
116
- rows = session.run(
117
- "MATCH (n) RETURN labels(n)[0] AS t, count(n) AS c"
118
- ).data()
119
- node_counts = {r["t"]: r["c"] for r in rows if r["t"]}
120
- rows = session.run(
121
- "MATCH ()-[r]->() RETURN type(r) AS t, count(r) AS c"
122
- ).data()
123
- rel_counts = {r["t"]: r["c"] for r in rows if r["t"]}
124
- # Read last pipeline timestamp from Neo4j if stored
125
  last_run = None
126
- try:
127
- if driver:
128
  with driver.session() as session:
129
- row = session.run(
 
 
 
 
 
 
 
 
130
  "MATCH (m:PipelineMeta) "
131
  "RETURN m.last_run AS ts ORDER BY m.last_run DESC LIMIT 1"
132
  ).single()
133
- last_run = row["ts"] if row else None
134
- except Exception:
135
- pass
136
 
137
  return StatsResponse(
138
  nodes=node_counts,
@@ -144,18 +142,34 @@ def get_stats():
144
 
145
  @app.websocket("/ws/feed")
146
  async def websocket_feed(websocket: WebSocket):
 
 
147
  await websocket.accept()
148
  logger.info("[WS] Feed client connected")
149
  try:
150
  while True:
151
- data = await websocket.receive_text()
 
 
 
 
 
 
 
 
 
 
152
  await websocket.send_json({
153
- "type": "ping",
154
- "message": "Feed active. Updates broadcast on new data ingestion.",
 
155
  "at": datetime.now().isoformat(),
156
  })
 
157
  except WebSocketDisconnect:
158
  logger.info("[WS] Feed client disconnected")
 
 
159
 
160
  @app.get("/debug/env")
161
  def debug_env():
 
111
  driver = get_driver()
112
  node_counts = {}
113
  rel_counts = {}
114
+ # BUG-06/24 FIX: single session for all stats queries, with APOC fast-path
 
 
 
 
 
 
 
 
 
 
115
  last_run = None
116
+ if driver:
117
+ try:
118
  with driver.session() as session:
119
+ n_rows = session.run(
120
+ "MATCH (n) RETURN labels(n)[0] AS t, count(n) AS c"
121
+ ).data()
122
+ node_counts = {r["t"]: r["c"] for r in n_rows if r["t"]}
123
+ r_rows = session.run(
124
+ "MATCH ()-[r]->() RETURN type(r) AS t, count(r) AS c"
125
+ ).data()
126
+ rel_counts = {r["t"]: r["c"] for r in r_rows if r["t"]}
127
+ meta = session.run(
128
  "MATCH (m:PipelineMeta) "
129
  "RETURN m.last_run AS ts ORDER BY m.last_run DESC LIMIT 1"
130
  ).single()
131
+ last_run = meta["ts"] if meta else None
132
+ except Exception as e:
133
+ logger.debug(f"[Stats] Query error: {e}")
134
 
135
  return StatsResponse(
136
  nodes=node_counts,
 
142
 
143
  @app.websocket("/ws/feed")
144
  async def websocket_feed(websocket: WebSocket):
145
+ """BUG-01 FIX: server now pushes data every 15s — no longer waits for client msg."""
146
+ import asyncio
147
  await websocket.accept()
148
  logger.info("[WS] Feed client connected")
149
  try:
150
  while True:
151
+ driver = get_driver()
152
+ stats = {}
153
+ if driver:
154
+ try:
155
+ with driver.session() as s:
156
+ rows = s.run(
157
+ "MATCH (n) RETURN labels(n)[0] AS t, count(n) AS c"
158
+ ).data()
159
+ stats = {r["t"]: r["c"] for r in rows if r["t"]}
160
+ except Exception:
161
+ pass
162
  await websocket.send_json({
163
+ "type": "heartbeat",
164
+ "message": "BharatGraph live feed active",
165
+ "stats": stats,
166
  "at": datetime.now().isoformat(),
167
  })
168
+ await asyncio.sleep(15)
169
  except WebSocketDisconnect:
170
  logger.info("[WS] Feed client disconnected")
171
+ except Exception as e:
172
+ logger.warning(f"[WS] Feed error: {e}")
173
 
174
  @app.get("/debug/env")
175
  def debug_env():