ForcePilot/backend/server/utils/lifespan.py
Kris 66916f9b36 feat(channel): 添加渠道网关服务端路由和端点
新增全渠道网关的 API 路由层和网关端点。

主要变更:
- channel_router.py: 渠道管理 API 路由(CRUD、配置、绑定等)
- gateway_sse_router.py: SSE 网关端点
- gateway_ws_router.py: WebSocket 网关端点
- webhook_router.py: Webhook 回调路由
- auth_router.py: 认证路由更新
- routers/__init__.py: 路由注册更新
- main.py: 主入口更新
- lifespan.py: 应用生命周期更新,渠道扩展加载与卸载
2026-05-21 12:09:29 +08:00

135 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from contextlib import asynccontextmanager
from fastapi import FastAPI
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
from yuxi.services.task_service import tasker
from yuxi.services.mcp_service import ensure_builtin_mcp_servers_in_db
from yuxi.services.model_provider_service import ensure_builtin_model_providers_in_db
from yuxi.services.subagent_service import init_builtin_subagents
from yuxi.services.run_queue_service import close_queue_clients, get_redis_client
from yuxi.storage.postgres.manager import pg_manager
from yuxi.knowledge import knowledge_base
from yuxi.utils import logger
from yuxi.agents.backends.sandbox import init_sandbox_provider, shutdown_sandbox_provider
from yuxi import get_version
@asynccontextmanager
async def lifespan(app: FastAPI):
"""FastAPI lifespan事件管理器"""
# 初始化数据库连接
try:
pg_manager.initialize()
await pg_manager.create_business_tables()
await pg_manager.ensure_business_schema()
await pg_manager.ensure_knowledge_schema()
except Exception as e:
logger.error(f"Failed to initialize database during startup: {e}")
# 确保内置 MCP 服务器定义存在于数据库
try:
await ensure_builtin_mcp_servers_in_db()
except Exception as e:
logger.error(f"Failed to ensure builtin MCP servers during startup: {e}")
# 初始化内置模型供应商配置
try:
async with pg_manager.get_async_session_context() as session:
await ensure_builtin_model_providers_in_db(session)
except Exception as e:
logger.error(f"Failed to ensure builtin model providers during startup: {e}")
# 初始化模型缓存v2 模型选择使用)
try:
from yuxi.services.model_cache import model_cache
from yuxi.services.model_provider_service import get_all_model_providers
async with pg_manager.get_async_session_context() as session:
providers = await get_all_model_providers(session)
model_cache.rebuild(providers)
except Exception as e:
logger.error(f"Failed to initialize model cache during startup: {e}")
# 初始化内置 SubAgent
try:
await init_builtin_subagents()
except Exception as e:
logger.error(f"Failed to initialize builtin subagents during startup: {e}")
raise
# 初始化知识库管理器
if os.environ.get("LITE_MODE", "").lower() in ("true", "1"):
logger.info("LITE_MODE enabled, skipping knowledge base initialization")
else:
try:
await knowledge_base.initialize()
except Exception as e:
logger.error(f"Failed to initialize knowledge base manager: {e}")
# 预热 Redisrun 队列)
try:
redis = await get_redis_client()
await redis.ping()
except Exception as e:
logger.warning(f"Run queue redis unavailable on startup: {e}")
try:
init_sandbox_provider()
except Exception as e:
logger.error(f"Failed to initialize sandbox provider during startup: {e}")
try:
from yuxi.channel.gateway.rpc_handlers import register_all_handlers
register_all_handlers()
logger.info("Gateway RPC handlers registered (%d methods)", 42)
except Exception as e:
logger.error(f"Failed to register gateway RPC handlers: {e}")
# =========================================================
# 2. 核心修复:在这里执行一次 setup(),建完表就拉倒
# =========================================================
checkpointer = AsyncPostgresSaver(pg_manager.langgraph_pool)
await checkpointer.setup()
print("LangGraph Checkpoint tables verified/created!")
try:
from yuxi.channel.runtime.manager import gateway
await gateway.boot()
trace = gateway.get_startup_trace()
if not trace.get("success"):
logger.error("ChannelGateway boot failed: %s", trace.get("error"))
else:
logger.info("ChannelGateway ready, %d channels, %.2fs",
len(gateway.list_channels()), trace.get("duration_seconds", 0))
except Exception as e:
logger.error("ChannelGateway boot error: %s", e)
await tasker.start()
logger.info(f"""
░██ ░██ ░██
░██ ░██
░██ ░██ ░██ ░██ ░██ ░██ ░██
░████ ░██ ░██ ░██ ░██ ░██
░██ ░██ ░██ ░█████ ░██
░██ ░██ ░███ ░██ ░██ ░██
░██ ░█████░██ ░██ ░██ ░██ v{get_version()}
""")
logger.info("Yuxi backend startup complete")
yield
await tasker.shutdown()
try:
from yuxi.channel.gateway.server import gateway_ws_server
await gateway_ws_server.shutdown()
except Exception as e:
logger.error(f"Gateway WS shutdown error: {e}")
shutdown_sandbox_provider()
await close_queue_clients()
await pg_manager.close()