2026-06-06 08:38:19 +08:00
|
|
|
"""
|
|
|
|
|
FastAPI 服务创建与配置
|
|
|
|
|
"""
|
|
|
|
|
import time
|
|
|
|
|
from contextlib import asynccontextmanager
|
|
|
|
|
|
|
|
|
|
from fastapi import FastAPI, Request
|
|
|
|
|
|
2026-06-24 13:03:15 +08:00
|
|
|
from app.utils.api_deps import get_rainfall_model, get_earthquake_model
|
2026-06-06 08:38:19 +08:00
|
|
|
from app.config.paths import get_logger
|
2026-06-19 17:04:03 +08:00
|
|
|
from config import settings
|
2026-06-06 08:38:19 +08:00
|
|
|
|
|
|
|
|
logger = get_logger("api")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@asynccontextmanager
|
|
|
|
|
async def lifespan(app: FastAPI):
|
2026-06-21 14:52:23 +08:00
|
|
|
"""应用生命周期:启动时预加载 DBN 模型"""
|
2026-06-06 08:38:19 +08:00
|
|
|
logger.info("正在预加载DBN模型...")
|
|
|
|
|
get_rainfall_model()
|
|
|
|
|
get_earthquake_model()
|
|
|
|
|
logger.info("DBN模型预加载完成")
|
2026-06-19 17:04:03 +08:00
|
|
|
|
2026-06-21 22:30:04 +08:00
|
|
|
# 检测 Docker QGIS 容器是否可用
|
|
|
|
|
try:
|
|
|
|
|
import subprocess
|
|
|
|
|
from app.services.qgis.qgis_env import get_docker_container
|
|
|
|
|
container = get_docker_container()
|
|
|
|
|
result = subprocess.run(
|
|
|
|
|
["docker", "inspect", "--format={{.State.Running}}", container],
|
|
|
|
|
capture_output=True, text=True, timeout=5,
|
|
|
|
|
)
|
|
|
|
|
if result.stdout.strip() == "true":
|
|
|
|
|
logger.info(f"Docker QGIS 容器 '{container}' 运行中")
|
|
|
|
|
else:
|
|
|
|
|
logger.warning(f"Docker QGIS 容器 '{container}' 未运行,专题图功能降级")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"Docker QGIS 检测失败: {e}")
|
2026-06-19 17:04:03 +08:00
|
|
|
|
2026-06-06 08:38:19 +08:00
|
|
|
yield
|
|
|
|
|
|
2026-06-19 17:04:03 +08:00
|
|
|
logger.info("应用关闭")
|
2026-06-06 08:38:19 +08:00
|
|
|
|
|
|
|
|
def create_app() -> FastAPI:
|
|
|
|
|
"""创建 FastAPI 应用实例"""
|
|
|
|
|
application = FastAPI(
|
|
|
|
|
title="西安灾害链预测服务",
|
|
|
|
|
description="基于动态贝叶斯网络的暴雨/地震灾害链预测API",
|
|
|
|
|
version="1.0.0",
|
|
|
|
|
lifespan=lifespan,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@application.middleware("http")
|
|
|
|
|
async def log_requests(request: Request, call_next):
|
|
|
|
|
"""请求日志中间件"""
|
|
|
|
|
start = time.time()
|
|
|
|
|
response = await call_next(request)
|
|
|
|
|
elapsed = time.time() - start
|
|
|
|
|
logger.info(f"{request.method} {request.url.path} -> {response.status_code} ({elapsed:.3f}s)")
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
# 注册路由
|
|
|
|
|
from app.api import register_routers
|
|
|
|
|
register_routers(application)
|
|
|
|
|
|
|
|
|
|
return application
|