mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-26 15:24:48 +08:00
Enforces config env var checks and improves startup handling (#892)
* Enforces config env var checks and improves startup handling Ensures critical environment variables are validated during config resolution, raising clear errors if missing. Improves server startup reliability by verifying that backend services are listening and by terminating on misconfiguration at launch. Adds more robust feedback to developers when API startup fails, reducing silent misconfigurations and speeding up troubleshooting. * Initial plan * Implement suggestions from PR #892: fix env var checks and improve error logging Co-authored-by: foreleven <4785594+foreleven@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: foreleven <4785594+foreleven@users.noreply.github.com> Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
7
Makefile
7
Makefile
@@ -187,7 +187,12 @@ dev:
|
|||||||
echo "✓ LangGraph server started on localhost:2024"; \
|
echo "✓ LangGraph server started on localhost:2024"; \
|
||||||
echo "Starting Gateway API..."; \
|
echo "Starting Gateway API..."; \
|
||||||
cd backend && uv run uvicorn src.gateway.app:app --host 0.0.0.0 --port 8001 > ../logs/gateway.log 2>&1 & \
|
cd backend && uv run uvicorn src.gateway.app:app --host 0.0.0.0 --port 8001 > ../logs/gateway.log 2>&1 & \
|
||||||
sleep 2; \
|
sleep 3; \
|
||||||
|
if ! lsof -i :8001 -sTCP:LISTEN -t >/dev/null 2>&1; then \
|
||||||
|
echo "✗ Gateway API failed to start. Last log output:"; \
|
||||||
|
tail -30 logs/gateway.log; \
|
||||||
|
cleanup; \
|
||||||
|
fi; \
|
||||||
echo "✓ Gateway API started on localhost:8001"; \
|
echo "✓ Gateway API started on localhost:8001"; \
|
||||||
echo "Starting Frontend..."; \
|
echo "Starting Frontend..."; \
|
||||||
cd frontend && pnpm run dev > ../logs/frontend.log 2>&1 & \
|
cd frontend && pnpm run dev > ../logs/frontend.log 2>&1 & \
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from src.agents.middlewares.title_middleware import TitleMiddleware
|
|||||||
from src.agents.middlewares.uploads_middleware import UploadsMiddleware
|
from src.agents.middlewares.uploads_middleware import UploadsMiddleware
|
||||||
from src.agents.middlewares.view_image_middleware import ViewImageMiddleware
|
from src.agents.middlewares.view_image_middleware import ViewImageMiddleware
|
||||||
from src.agents.thread_state import ThreadState
|
from src.agents.thread_state import ThreadState
|
||||||
|
from src.config.app_config import get_app_config
|
||||||
from src.config.summarization_config import get_summarization_config
|
from src.config.summarization_config import get_summarization_config
|
||||||
from src.models import create_chat_model
|
from src.models import create_chat_model
|
||||||
from src.sandbox.middleware import SandboxMiddleware
|
from src.sandbox.middleware import SandboxMiddleware
|
||||||
@@ -213,7 +214,6 @@ def _build_middlewares(config: RunnableConfig):
|
|||||||
|
|
||||||
# Add ViewImageMiddleware only if the current model supports vision
|
# Add ViewImageMiddleware only if the current model supports vision
|
||||||
model_name = config.get("configurable", {}).get("model_name") or config.get("configurable", {}).get("model")
|
model_name = config.get("configurable", {}).get("model_name") or config.get("configurable", {}).get("model")
|
||||||
from src.config import get_app_config
|
|
||||||
|
|
||||||
app_config = get_app_config()
|
app_config = get_app_config()
|
||||||
# If no model_name specified, use the first model (default)
|
# If no model_name specified, use the first model (default)
|
||||||
|
|||||||
@@ -113,7 +113,10 @@ class AppConfig(BaseModel):
|
|||||||
"""
|
"""
|
||||||
if isinstance(config, str):
|
if isinstance(config, str):
|
||||||
if config.startswith("$"):
|
if config.startswith("$"):
|
||||||
return os.getenv(config[1:], config)
|
env_value = os.getenv(config[1:])
|
||||||
|
if env_value is None:
|
||||||
|
raise ValueError(f"Environment variable {config[1:]} not found for config value {config}")
|
||||||
|
return env_value
|
||||||
return config
|
return config
|
||||||
elif isinstance(config, dict):
|
elif isinstance(config, dict):
|
||||||
return {k: cls.resolve_env_variables(v) for k, v in config.items()}
|
return {k: cls.resolve_env_variables(v) for k, v in config.items()}
|
||||||
|
|||||||
@@ -130,8 +130,9 @@ class ExtensionsConfig(BaseModel):
|
|||||||
for key, value in config.items():
|
for key, value in config.items():
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
if value.startswith("$"):
|
if value.startswith("$"):
|
||||||
env_value = os.getenv(value[1:], None)
|
env_value = os.getenv(value[1:])
|
||||||
if env_value is not None:
|
if env_value is None:
|
||||||
|
raise ValueError(f"Environment variable {value[1:]} not found for config value {value}")
|
||||||
config[key] = env_value
|
config[key] = env_value
|
||||||
else:
|
else:
|
||||||
config[key] = value
|
config[key] = value
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
from collections.abc import AsyncGenerator
|
from collections.abc import AsyncGenerator
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
from src.config.app_config import get_app_config
|
||||||
from src.gateway.config import get_gateway_config
|
from src.gateway.config import get_gateway_config
|
||||||
from src.gateway.routers import artifacts, mcp, memory, models, skills, uploads
|
from src.gateway.routers import artifacts, mcp, memory, models, skills, uploads
|
||||||
|
|
||||||
@@ -20,6 +22,14 @@ logger = logging.getLogger(__name__)
|
|||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
|
||||||
"""Application lifespan handler."""
|
"""Application lifespan handler."""
|
||||||
|
|
||||||
|
# Load config and check necessary environment variables at startup
|
||||||
|
try:
|
||||||
|
get_app_config()
|
||||||
|
logger.info("Configuration loaded successfully")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Failed to load configuration: {e}")
|
||||||
|
sys.exit(1)
|
||||||
config = get_gateway_config()
|
config = get_gateway_config()
|
||||||
logger.info(f"Starting API Gateway on {config.host}:{config.port}")
|
logger.info(f"Starting API Gateway on {config.host}:{config.port}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user