f0fcea03bb
2.新启动脚本制作
225 lines
7.9 KiB
Python
225 lines
7.9 KiB
Python
"""
|
|
简道云 FastAPI 服务 - 主应用入口
|
|
|
|
本文件是 FastAPI 应用的主入口文件,负责:
|
|
1. 应用初始化和生命周期管理
|
|
2. 模块注册和路由配置
|
|
3. 异常处理器配置
|
|
4. 中间件配置
|
|
|
|
作者: 项目团队
|
|
版本: 2.0.0
|
|
"""
|
|
from contextlib import asynccontextmanager
|
|
from fastapi import FastAPI, Request, HTTPException, status
|
|
from fastapi.responses import JSONResponse
|
|
from fastapi.exceptions import RequestValidationError
|
|
import logging
|
|
|
|
from app.utils.app_tools import AppTools, setup_global_logger
|
|
from app.module.f6_plugin_module import F6PluginModule
|
|
from app.module.module import F6Module
|
|
from app.module.other_module import OtherPluginModule
|
|
from app.config import Config
|
|
from app.schemas import ErrorResponse
|
|
from app.core import core_manager
|
|
from app.api.routes import router
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
"""应用生命周期管理 - 启动和关闭"""
|
|
# 启动时初始化
|
|
app.state.app_tools = AppTools(Config)
|
|
app.state.logger = setup_global_logger(Config)
|
|
|
|
# 初始化业务模块
|
|
f6_module = F6Module()
|
|
f6_plugin_module = F6PluginModule()
|
|
other_module = OtherPluginModule()
|
|
|
|
# 将模块实例存储到 app.state(用于依赖注入)
|
|
app.state.f6_module = f6_module
|
|
app.state.f6_plugin_module = f6_plugin_module
|
|
app.state.other_module = other_module
|
|
|
|
# 注册模块到 registry
|
|
core_manager.initialize_modules({
|
|
'f6_module': f6_module,
|
|
'f6_plugin_module': f6_plugin_module,
|
|
'other_module': other_module
|
|
})
|
|
|
|
# 注册所有操作到 module_registry
|
|
core_manager.register_action('login_in', f6_module.accept_login_message, 'f6_module',
|
|
description='F6系统登录')
|
|
core_manager.register_action('get_company_information', f6_module.get_company_information, 'f6_module',
|
|
description='获取公司信息')
|
|
core_manager.register_action('get_store_information', f6_module.get_store_information, 'f6_module',
|
|
description='获取门店信息')
|
|
core_manager.register_action('keep_alive', f6_module.get_keep_heart, 'f6_module',
|
|
description='保持连接')
|
|
core_manager.register_action('check_file', f6_plugin_module.check_file, 'f6_plugin_module',
|
|
description='校验上传文件')
|
|
core_manager.register_action('create_brand', f6_plugin_module.create_brand, 'f6_plugin_module',
|
|
description='创建品牌')
|
|
core_manager.register_action('delete_history', f6_plugin_module.delete_history, 'f6_plugin_module',
|
|
description='删除历史记录')
|
|
core_manager.register_action('delete_customer', f6_plugin_module.delete_customer, 'f6_plugin_module',
|
|
description='删除客户')
|
|
core_manager.register_action('delete_cars', f6_plugin_module.delete_cars, 'f6_plugin_module',
|
|
description='删除车辆')
|
|
core_manager.register_action('sms_signature_status', other_module.sms_signature_status, 'other_module',
|
|
description='短信签名状态')
|
|
core_manager.register_action('modify_customer_info', f6_plugin_module.modify_customer_info, 'f6_plugin_module',
|
|
description='修改客户信息')
|
|
core_manager.register_action('disable_project', f6_plugin_module.disable_projects, 'f6_plugin_module',
|
|
description='项目信息批量启停')
|
|
core_manager.register_action('batch_modify_materials', f6_plugin_module.modify_material, 'f6_plugin_module',
|
|
description='材料信息批量修改')
|
|
core_manager.register_action('batch_modify_projects', f6_plugin_module.modify_project, 'f6_plugin_module',
|
|
description='项目信息批量修改')
|
|
core_manager.register_action('bi_task', f6_plugin_module.bi_task, 'f6_plugin_module',
|
|
description='BI任务')
|
|
|
|
app.state.logger.info("应用启动完成,已注册所有操作")
|
|
|
|
yield
|
|
|
|
# 关闭时清理资源
|
|
if hasattr(app.state, 'app_tools') and hasattr(app.state.app_tools, 'scheduler'):
|
|
app.state.app_tools.scheduler.shutdown(wait=False)
|
|
app.state.logger.info("应用关闭")
|
|
|
|
app = FastAPI(
|
|
title="简道云FastAPI服务",
|
|
description="简道云插件后端服务,提供数据同步和处理功能",
|
|
version="2.0.0",
|
|
lifespan=lifespan
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# 注册路由
|
|
app.include_router(router)
|
|
|
|
|
|
@app.get("/", tags=["系统"])
|
|
async def root():
|
|
"""
|
|
根路径端点
|
|
|
|
返回服务基本信息和可用端点
|
|
"""
|
|
return {
|
|
"service": "简道云FastAPI服务",
|
|
"version": "2.0.0",
|
|
"status": "running",
|
|
"endpoints": {
|
|
"health": "/health",
|
|
"webhook": "/webhook",
|
|
"docs": "/docs",
|
|
"redoc": "/redoc"
|
|
}
|
|
}
|
|
|
|
|
|
@app.exception_handler(HTTPException)
|
|
async def http_exception_handler(request: Request, exc: HTTPException):
|
|
"""
|
|
HTTP 异常处理器
|
|
|
|
处理所有 HTTPException 异常,返回统一的错误响应格式。
|
|
|
|
Args:
|
|
request: FastAPI 请求对象
|
|
exc: HTTPException 异常对象
|
|
|
|
Returns:
|
|
JSONResponse: 包含错误详情的 JSON 响应
|
|
"""
|
|
logger = getattr(app.state, 'logger', None)
|
|
if logger:
|
|
logger.error(f"HTTP异常: {exc.status_code} - {exc.detail}")
|
|
return JSONResponse(
|
|
status_code=exc.status_code,
|
|
content=ErrorResponse(
|
|
detail=exc.detail or "HTTP error",
|
|
error_code=f"HTTP_{exc.status_code}"
|
|
).model_dump(),
|
|
)
|
|
|
|
|
|
@app.exception_handler(RequestValidationError)
|
|
async def validation_exception_handler(request: Request, exc: RequestValidationError):
|
|
"""
|
|
请求验证异常处理器
|
|
|
|
处理 Pydantic 数据验证失败的情况,返回详细的验证错误信息。
|
|
|
|
Args:
|
|
request: FastAPI 请求对象
|
|
exc: RequestValidationError 异常对象
|
|
|
|
Returns:
|
|
JSONResponse: 包含验证错误详情的 JSON 响应
|
|
"""
|
|
logger = getattr(app.state, 'logger', None)
|
|
if logger:
|
|
logger.warning(f"请求验证失败: {exc.errors()}")
|
|
return JSONResponse(
|
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
content=ErrorResponse(
|
|
detail="请求数据验证失败",
|
|
error_code="VALIDATION_ERROR"
|
|
).model_dump(),
|
|
)
|
|
|
|
|
|
@app.exception_handler(Exception)
|
|
async def general_exception_handler(request: Request, exc: Exception):
|
|
"""
|
|
通用异常处理器
|
|
|
|
捕获所有未处理的异常,防止应用崩溃,并记录详细的错误信息。
|
|
|
|
Args:
|
|
request: FastAPI 请求对象
|
|
exc: 异常对象
|
|
|
|
Returns:
|
|
JSONResponse: 包含错误详情的 JSON 响应
|
|
"""
|
|
logger = getattr(app.state, 'logger', None)
|
|
if logger:
|
|
logger.error(f"未处理的异常: {type(exc).__name__} - {str(exc)}", exc_info=True)
|
|
return JSONResponse(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
content=ErrorResponse(
|
|
detail="服务器内部错误",
|
|
error_code="INTERNAL_ERROR"
|
|
).model_dump(),
|
|
)
|
|
# 路由已移动到 app/api/routes.py
|
|
|
|
|
|
if __name__ == '__main__':
|
|
"""
|
|
直接运行入口
|
|
|
|
当直接运行此文件时,启动 uvicorn 服务器。
|
|
默认配置:
|
|
- 主机: 0.0.0.0 (监听所有网络接口)
|
|
- 端口: 5000
|
|
- 热重载: 关闭 (生产环境建议关闭)
|
|
"""
|
|
import uvicorn
|
|
uvicorn.run(app, host="0.0.0.0", port=5000, reload=False)
|