Spaces:
Sleeping
Sleeping
SemSorter commited on
Commit ·
c27555f
1
Parent(s): fee931d
Initialize simulation as background task to fix WS timeout on Render
Browse files- SemSorter/server/app.py +7 -14
SemSorter/server/app.py
CHANGED
|
@@ -140,11 +140,16 @@ async def _simulation_tick_loop() -> None:
|
|
| 140 |
|
| 141 |
@app.on_event("startup")
|
| 142 |
async def startup():
|
| 143 |
-
global _main_loop, _frame_ready_event
|
| 144 |
_main_loop = asyncio.get_running_loop()
|
| 145 |
_frame_ready_event = asyncio.Event()
|
| 146 |
bridge.set_frame_ready_event(_main_loop, _frame_ready_event)
|
| 147 |
-
logger.info("Server ready
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
|
| 150 |
@app.on_event("shutdown")
|
|
@@ -231,12 +236,6 @@ async def ws_chat(ws: WebSocket):
|
|
| 231 |
_chat_clients.add(ws)
|
| 232 |
logger.info("Chat client connected (%d total)", len(_chat_clients))
|
| 233 |
|
| 234 |
-
# Lazily start simulation if this is the first client
|
| 235 |
-
if _sim_tick_task is None:
|
| 236 |
-
logger.info("First client connected; starting MuJoCo simulation...")
|
| 237 |
-
await bridge.run_in_sim_thread(bridge.get_simulation)
|
| 238 |
-
_sim_tick_task = asyncio.create_task(_simulation_tick_loop())
|
| 239 |
-
|
| 240 |
try:
|
| 241 |
await ws.send_text(json.dumps({
|
| 242 |
"type": "welcome",
|
|
@@ -323,12 +322,6 @@ async def ws_video(ws: WebSocket):
|
|
| 323 |
_video_clients.add(ws)
|
| 324 |
logger.info("Video client connected")
|
| 325 |
|
| 326 |
-
# Lazily start simulation if this is the first client
|
| 327 |
-
if _sim_tick_task is None:
|
| 328 |
-
logger.info("First client connected; starting MuJoCo simulation...")
|
| 329 |
-
await bridge.run_in_sim_thread(bridge.get_simulation)
|
| 330 |
-
_sim_tick_task = asyncio.create_task(_simulation_tick_loop())
|
| 331 |
-
|
| 332 |
try:
|
| 333 |
while True:
|
| 334 |
# Wait for new frame (event-driven; sends exactly when sim produces one)
|
|
|
|
| 140 |
|
| 141 |
@app.on_event("startup")
|
| 142 |
async def startup():
|
| 143 |
+
global _main_loop, _frame_ready_event, _sim_tick_task
|
| 144 |
_main_loop = asyncio.get_running_loop()
|
| 145 |
_frame_ready_event = asyncio.Event()
|
| 146 |
bridge.set_frame_ready_event(_main_loop, _frame_ready_event)
|
| 147 |
+
logger.info("Server ready. Backgrounding simulation initialization...")
|
| 148 |
+
|
| 149 |
+
# Initialize the simulation asynchronously in the background so it doesn't block
|
| 150 |
+
# the main event loop and cause WS timeouts on low-CPU instances like Render Free Tier.
|
| 151 |
+
asyncio.create_task(bridge.run_in_sim_thread(bridge.get_simulation))
|
| 152 |
+
_sim_tick_task = asyncio.create_task(_simulation_tick_loop())
|
| 153 |
|
| 154 |
|
| 155 |
@app.on_event("shutdown")
|
|
|
|
| 236 |
_chat_clients.add(ws)
|
| 237 |
logger.info("Chat client connected (%d total)", len(_chat_clients))
|
| 238 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
try:
|
| 240 |
await ws.send_text(json.dumps({
|
| 241 |
"type": "welcome",
|
|
|
|
| 322 |
_video_clients.add(ws)
|
| 323 |
logger.info("Video client connected")
|
| 324 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 325 |
try:
|
| 326 |
while True:
|
| 327 |
# Wait for new frame (event-driven; sends exactly when sim produces one)
|