mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-08-31 14:30:13 +03:00
feat: improve async handling in LLM config retrieval
Refactor get_llm_config to handle various async contexts more robustly. The function now properly checks for running event loops using asyncio.get_running_loop() and handles edge cases when called from thread pools or existing loops. This prevents RuntimeErrors and ensures reliable execution in both sync and async environments.
This commit is contained in:
parent
d8c3a56503
commit
4765e54d7a
@ -363,6 +363,7 @@ def get_llm_config(user_id, jwt_token: str) -> Optional[dict]:
|
||||
api_key = config['api_key']
|
||||
"""
|
||||
import asyncio
|
||||
import threading
|
||||
|
||||
try:
|
||||
# Convert user_id to UUID if it's a string
|
||||
@ -375,10 +376,12 @@ def get_llm_config(user_id, jwt_token: str) -> Optional[dict]:
|
||||
# Import the async helper
|
||||
from gns3server.agent.gns3_copilot.utils.llm_config_helper import get_user_llm_config
|
||||
|
||||
# Run async function in sync context
|
||||
loop = asyncio.get_event_loop()
|
||||
if loop.is_running():
|
||||
# If loop is already running, run in a new thread
|
||||
# Check if we're in the main thread with a running event loop
|
||||
try:
|
||||
loop = asyncio.get_running_loop()
|
||||
# We're in an async context with a running loop
|
||||
# This shouldn't happen since this is a sync function,
|
||||
# but if it does, we need to run in a separate thread
|
||||
import concurrent.futures
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
future = executor.submit(
|
||||
@ -386,9 +389,36 @@ def get_llm_config(user_id, jwt_token: str) -> Optional[dict]:
|
||||
get_user_llm_config(user_id, jwt_token, url)
|
||||
)
|
||||
return future.result(timeout=10)
|
||||
else:
|
||||
# No loop running, use run() directly
|
||||
return asyncio.run(get_user_llm_config(user_id, jwt_token, url))
|
||||
except RuntimeError:
|
||||
# No running event loop - we're in a sync context (possibly a thread pool)
|
||||
# This is the expected path for our use case
|
||||
pass
|
||||
|
||||
# Try to get an existing event loop, or create a new one
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
if loop.is_running():
|
||||
# Loop is running but not the running loop (edge case)
|
||||
# Create a new loop in a thread
|
||||
import concurrent.futures
|
||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||
future = executor.submit(
|
||||
asyncio.run,
|
||||
get_user_llm_config(user_id, jwt_token, url)
|
||||
)
|
||||
return future.result(timeout=10)
|
||||
else:
|
||||
# Loop exists but not running - use it
|
||||
return loop.run_until_complete(get_user_llm_config(user_id, jwt_token, url))
|
||||
except RuntimeError:
|
||||
# No event loop exists - create a new one
|
||||
# This happens when called from a thread pool executor
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
try:
|
||||
return loop.run_until_complete(get_user_llm_config(user_id, jwt_token, url))
|
||||
finally:
|
||||
loop.close()
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Failed to get LLM config for user %s: %s", user_id, e)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user