142 lines
5.5 KiB
Python
142 lines
5.5 KiB
Python
import asyncio
|
||
import os
|
||
from contextlib import asynccontextmanager
|
||
from fastapi import FastAPI
|
||
from services import offline_audio_cache
|
||
from services.device_config import DeviceConfigManager
|
||
from services.schedule_session_cleanup import background_cleanup_task
|
||
from services.role_manager import role_manager
|
||
from services.task_manager import task_manager
|
||
from initialization import register_services, init_directories
|
||
from config import settings
|
||
from utils.logger import session_logger
|
||
from api import api_router
|
||
from api.assets import configure_static_assets
|
||
from banban.routers import banban_router
|
||
from banban.middleware.auth import install_auth_middleware
|
||
from banban.middleware.request_log import install_request_logging_middleware
|
||
from database.init_db import init_db
|
||
from database.connection import get_db_manager
|
||
from services.firmware_scanner import firmware_scanner
|
||
from handlers.mqtt_handler import TalkingQMQTTService
|
||
from services.scheduler import TaskScheduler
|
||
|
||
device_config_manager = DeviceConfigManager()
|
||
|
||
|
||
@asynccontextmanager
|
||
async def lifespan(app: FastAPI):
|
||
worker_id = os.environ.get("UVICORN_WID", "0")
|
||
is_main_process = worker_id == "0"
|
||
if is_main_process:
|
||
session_logger.system_info(
|
||
"startup",
|
||
f"服务器启动,HTTP服务地址: http://{settings.server_host}:{settings.server_port}",
|
||
)
|
||
init_directories()
|
||
|
||
try:
|
||
session_logger.system_info("startup", "初始化数据库...")
|
||
await init_db()
|
||
session_logger.system_info("startup", "数据库初始化和迁移完成")
|
||
except Exception as e:
|
||
session_logger.system_info("startup", f"数据库初始化失败: {str(e)}")
|
||
|
||
scheduler = TaskScheduler.get_instance()
|
||
scheduler.start()
|
||
scheduler.add_interval_task(
|
||
interval_seconds=settings.talkingq_mqtt_nfc_notice_interval
|
||
)
|
||
if settings.talkingq_mqtt_broker:
|
||
mqtt_config = {
|
||
"broker": settings.talkingq_mqtt_broker,
|
||
"port": settings.talkingq_mqtt_port,
|
||
"username": settings.talkingq_mqtt_username,
|
||
"password": settings.talkingq_mqtt_password,
|
||
"device_prefix": settings.talkingq_mqtt_device_prefix,
|
||
"qos": settings.talkingq_mqtt_qos,
|
||
"keepalive": settings.talkingq_mqtt_keepalive,
|
||
"nfc_notice_interval": settings.talkingq_mqtt_nfc_notice_interval,
|
||
}
|
||
service = await TalkingQMQTTService.get_instance(mqtt_config)
|
||
await service.connect()
|
||
session_logger.system_info("startup", "TalkingQ MQTT 设备命令服务链接已启动")
|
||
else:
|
||
session_logger.system_info("startup", "未配置 TalkingQ_MQTT,MQTT 服务链接未启动")
|
||
exit(1)
|
||
|
||
await role_manager.initialize()
|
||
await register_services()
|
||
|
||
try:
|
||
await firmware_scanner.scan_firmware_files()
|
||
session_logger.system_info("startup", "固件文件扫描完成")
|
||
except Exception as e:
|
||
session_logger.system_info("startup", f"固件文件扫描失败: {str(e)}")
|
||
|
||
session_logger.system_info("startup", "中断处理服务已初始化")
|
||
|
||
cleanup_task = asyncio.create_task(background_cleanup_task())
|
||
try:
|
||
yield
|
||
finally:
|
||
cleanup_task.cancel()
|
||
try:
|
||
await asyncio.wait_for(cleanup_task, timeout=5.0)
|
||
except (asyncio.CancelledError, asyncio.TimeoutError):
|
||
if is_main_process:
|
||
session_logger.system_info("shutdown", "后台清理任务已取消")
|
||
|
||
from services.audio_session import audio_session_manager
|
||
|
||
sessions_to_close = await audio_session_manager.get_all_sessions()
|
||
|
||
for session_key, session in sessions_to_close:
|
||
try:
|
||
if session.send_task:
|
||
session.send_task.cancel()
|
||
if hasattr(session, "asr_service") and session.asr_service:
|
||
await session.asr_service.close()
|
||
if hasattr(session, "llm_service") and session.llm_service:
|
||
await session.llm_service.close()
|
||
except Exception as e:
|
||
if is_main_process:
|
||
session_logger.system_info("shutdown", f"清理会话时出错: {str(e)}")
|
||
|
||
# 清理所有任务管理器的任务
|
||
try:
|
||
await task_manager.cleanup_all_tasks()
|
||
if is_main_process:
|
||
session_logger.system_info("shutdown", "任务管理器清理完成")
|
||
except Exception as e:
|
||
if is_main_process:
|
||
session_logger.system_info("shutdown", f"任务管理器清理时出错: {str(e)}")
|
||
|
||
try:
|
||
db_manager = await get_db_manager()
|
||
await db_manager.close()
|
||
if is_main_process:
|
||
session_logger.system_info("shutdown", "数据库连接已关闭")
|
||
except Exception as e:
|
||
if is_main_process:
|
||
session_logger.system_info("shutdown", f"关闭数据库连接时出错: {str(e)}")
|
||
|
||
TaskScheduler.reset_instance()
|
||
await TalkingQMQTTService.reset_instance()
|
||
session_logger.system_info("shutdown", "TalkingQ MQTT 服务链接已关闭")
|
||
|
||
if is_main_process:
|
||
session_logger.system_info("shutdown", "应用关闭")
|
||
|
||
|
||
app = FastAPI(lifespan=lifespan)
|
||
|
||
configure_static_assets(app)
|
||
|
||
# 安装中间件
|
||
install_request_logging_middleware(app)
|
||
install_auth_middleware(app)
|
||
|
||
app.include_router(api_router)
|
||
app.include_router(banban_router)
|