11import asyncio
2+ from contextlib import asynccontextmanager
23import json
34import logging
45import os
89from watchdog .observers import Observer
910
1011import uvicorn
11- from fastapi import WebSocket , WebSocketDisconnect
12+ from fastapi import FastAPI , WebSocket , WebSocketDisconnect
1213
1314from eval_protocol .dataset_logger import default_logger
1415from eval_protocol .utils .vite_server import ViteServer
@@ -85,6 +86,7 @@ def broadcast_file_update(self, update_type: str, file_path: str):
8586 """Broadcast file update to all connected clients."""
8687 if not file_path .startswith (default_logger .datasets_dir ):
8788 return
89+ logger .info (f"Broadcasting file update: { update_type } { file_path } " )
8890
8991 message = {"type" : update_type , "path" : file_path , "timestamp" : time .time ()}
9092 # Include file contents for created and modified events
@@ -126,19 +128,29 @@ def __init__(
126128 os .path .join (os .path .dirname (os .path .dirname (os .path .dirname (__file__ ))), "vite-app" , "dist" )
127129 ),
128130 host : str = "localhost" ,
129- port : int = 4789 ,
131+ port : Optional [ int ] = None ,
130132 index_file : str = "index.html" ,
131133 watch_paths : Optional [List [str ]] = None ,
132134 ):
133- super ().__init__ (build_dir , host , port , index_file )
134-
135135 # Initialize WebSocket manager
136136 self .websocket_manager = WebSocketManager ()
137137
138138 # Set up file watching
139139 self .watch_paths = watch_paths or [os .getcwd ()]
140140 self .observer = Observer ()
141141 self .file_watcher = FileWatcher (self .websocket_manager )
142+ self ._file_watching_started = False
143+
144+ @asynccontextmanager
145+ async def lifespan (app : FastAPI ):
146+ print ("before" )
147+ self .start_file_watching ()
148+ self .websocket_manager ._loop = asyncio .get_running_loop ()
149+ yield
150+ print ("after" )
151+ self .stop_file_watching ()
152+
153+ super ().__init__ (build_dir , host , port , index_file , lifespan = lifespan )
142154
143155 # Add WebSocket endpoint
144156 self ._setup_websocket_routes ()
@@ -174,6 +186,11 @@ async def status():
174186
175187 def start_file_watching (self ):
176188 """Start watching file system for changes."""
189+ # Check if file watching has already been started
190+ if self ._file_watching_started :
191+ logger .info ("File watching already started, skipping" )
192+ return
193+
177194 for path in self .watch_paths :
178195 if os .path .exists (path ):
179196 self .observer .schedule (self .file_watcher , path , recursive = True )
@@ -182,15 +199,18 @@ def start_file_watching(self):
182199 logger .warning (f"Watch path does not exist: { path } " )
183200
184201 self .observer .start ()
202+ self ._file_watching_started = True
185203 logger .info ("File watching started" )
186204
187205 def stop_file_watching (self ):
188206 """Stop watching file system."""
189- self .observer .stop ()
190- self .observer .join ()
191- logger .info ("File watching stopped" )
207+ if self ._file_watching_started :
208+ self .observer .stop ()
209+ self .observer .join ()
210+ self ._file_watching_started = False
211+ logger .info ("File watching stopped" )
192212
193- async def run_async (self , reload : bool = False ):
213+ async def run_async (self ):
194214 """
195215 Run the logs server asynchronously with file watching.
196216
@@ -212,10 +232,9 @@ async def run_async(self, reload: bool = False):
212232 self .app ,
213233 host = self .host ,
214234 port = self .port ,
215- reload = reload ,
216- reload_dirs = self .watch_paths ,
217235 log_level = "info" ,
218236 )
237+
219238 server = uvicorn .Server (config )
220239 await server .serve ()
221240
@@ -224,22 +243,21 @@ async def run_async(self, reload: bool = False):
224243 finally :
225244 self .stop_file_watching ()
226245
227- def run (self , reload : bool = False ):
246+ def run (self ):
228247 """
229248 Run the logs server with file watching.
230249
231250 Args:
232251 reload: Whether to enable auto-reload (default: False)
233252 """
234- asyncio .run (self .run_async (reload ))
253+ asyncio .run (self .run_async ())
254+
255+
256+ server = LogsServer ()
257+ app = server .app
235258
236259
237- def serve_logs (
238- host : str = "localhost" ,
239- port : int = 4789 ,
240- watch_paths : Optional [List [str ]] = None ,
241- reload : bool = False ,
242- ):
260+ def serve_logs ():
243261 """
244262 Convenience function to create and run a LogsServer.
245263
@@ -251,9 +269,8 @@ def serve_logs(
251269 watch_paths: List of paths to watch for file changes
252270 reload: Whether to enable auto-reload
253271 """
254- server = LogsServer (host = host , port = port , watch_paths = watch_paths )
255- server .run (reload = reload )
272+ server .run ()
256273
257274
258275if __name__ == "__main__" :
259- serve_logs (reload = True )
276+ serve_logs ()
0 commit comments