PhoneWork/router/main.py
Yuyao Huang (Sam) c0ecea9d3a refactor: 将应用实例创建移至模块级别并优化主程序
将应用实例创建从主程序移至模块级别,避免重复创建实例
主程序现在直接使用模块级别的应用实例,简化了启动逻辑
2026-03-29 16:50:55 +08:00

96 lines
2.3 KiB
Python

"""Router main module - FastAPI app factory.
Creates the FastAPI application with:
- Feishu WebSocket client
- Node WebSocket endpoint
- Health check endpoints
"""
from __future__ import annotations
import logging
from typing import Optional
from fastapi import FastAPI, WebSocket
from fastapi.middleware.cors import CORSMiddleware
from bot.handler import start_websocket_client
from router.nodes import NodeRegistry, get_node_registry
from router.ws import ws_node_endpoint
logger = logging.getLogger(__name__)
def create_app(router_secret: Optional[str] = None) -> FastAPI:
"""Create the FastAPI application.
Args:
router_secret: Secret for authenticating host client connections
"""
app = FastAPI(title="PhoneWork Router", version="3.0.0")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
registry = get_node_registry()
if router_secret:
registry._secret = router_secret
@app.get("/health")
async def health():
from router.rpc import get_pending_count
nodes = registry.list_nodes()
online_nodes = [n for n in nodes if n["status"] == "online"]
return {
"status": "ok",
"nodes": nodes,
"online_nodes": len(online_nodes),
"total_nodes": len(nodes),
"pending_requests": get_pending_count(),
}
@app.get("/nodes")
async def list_nodes():
return registry.list_nodes()
@app.websocket("/ws/node")
async def ws_node(websocket: WebSocket):
await ws_node_endpoint(websocket)
@app.on_event("startup")
async def startup():
import asyncio
loop = asyncio.get_running_loop()
start_websocket_client(loop)
logger.info("Router started")
@app.on_event("shutdown")
async def shutdown():
logger.info("Router shut down")
return app
# Create top-level app instance for uvicorn
from config import ROUTER_SECRET
app = create_app(router_secret=ROUTER_SECRET)
if __name__ == "__main__":
from config import PORT
import uvicorn
uvicorn.run(
"router.main:app",
host="0.0.0.0",
port=PORT,
reload=False,
log_level="info",
ws_ping_interval=20,
ws_ping_timeout=60,
)