fix: run execute_command_sync in thread pool to avoid event loop conflict (#468)
When async_processing=False, the sync path calls execute_command_sync() which internally uses asyncio.run(). This fails when called from FastAPI's already-running event loop with 'asyncio.run() cannot be called from a running event loop'. Wrapping the call in asyncio.to_thread() runs it in a thread pool executor, avoiding the event loop conflict while preserving the synchronous behavior from the API consumer's perspective. Fixes #453
This commit is contained in:
parent
28936d3944
commit
f14020d385
1 changed files with 7 additions and 2 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
import asyncio
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, List, Optional
|
from typing import Any, List, Optional
|
||||||
|
|
@ -449,11 +450,15 @@ async def create_source(
|
||||||
embed=source_data.embed,
|
embed=source_data.embed,
|
||||||
)
|
)
|
||||||
|
|
||||||
result = execute_command_sync(
|
# Run in thread pool to avoid blocking the event loop
|
||||||
|
# execute_command_sync uses asyncio.run() internally which can't
|
||||||
|
# be called from an already-running event loop (FastAPI)
|
||||||
|
result = await asyncio.to_thread(
|
||||||
|
execute_command_sync,
|
||||||
"open_notebook", # app name
|
"open_notebook", # app name
|
||||||
"process_source", # command name
|
"process_source", # command name
|
||||||
command_input.model_dump(),
|
command_input.model_dump(),
|
||||||
timeout=300, # 5 minute timeout for sync processing
|
300, # 5 minute timeout for sync processing
|
||||||
)
|
)
|
||||||
|
|
||||||
if not result.is_success():
|
if not result.is_success():
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue