Files
next-tjwater-server/README.md
T
jiang be6317eb48 feat(server): integrate MCP queries and investigation messaging
Add project-bound OAuth MCP queries and controlled analysis with scoped evidence,
limits, timeouts and a nearby-model spatial query using EPSG:4326 inputs.
Default nearby searches to 200 meters and five results.

Integrate investigation messaging/presentation, health/readiness and typed history;
remove duplicate web search and fix online simulation and compressed baseline writes.
Include project migrations 023-025; keep local credentials and demo seeding excluded.

Validation: 319 focused pytest checks; real PostGIS temporary-table regression;
read-only Jinqian bridge radius comparison; cross-language MCP discovery/calls.
2026-10-19 18:46:58 +08:00

7.8 KiB
Raw Blame History

TJWaterServerBinary 内部后端

TJWaterServerBinary 是 TJWater 内部版 Python 后端,基于 FastAPI 提供认证、项目、管网、模拟、爆管、漏损、SCADA 和地图服务集成能力。该仓库用于内部开发和完整功能维护。

技术栈

  • Python 3.12
  • FastAPI / Uvicorn
  • Pydantic / SQLAlchemy / psycopg
  • PostgreSQL、PostGIS、TimescaleDB
  • WNTR、EPANET、Cython、科学计算与空间分析依赖
  • pytest

目录结构

app/main.py           FastAPI 入口
app/api/              HTTP API 路由
app/auth/             认证和权限上下文
app/core/             配置、日志和基础设施初始化
app/domain/           领域模型和 Pydantic schema
app/infra/            数据库、EPANET 和外部集成
app/services/         业务服务编排
app/algorithms/       管网算法、模拟、爆管、漏损、清洗和健康分析
app/native/           本地管网数据读写与转换
tests/                后端测试
resources/            SQL、模板和示例资源
infra/docker/         Docker Compose 编排

本地开发

推荐使用已有 conda 环境:

conda run -n server python -m pytest tests/unit tests/auth -q
conda run -n server uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

如需要进入环境:

conda activate server

GET /health 是无需鉴权的 HTTP 服务存活检查,返回 200 和 {"status":"ok"},不查询数据库。 GET /ready 检查应用启动状态、元数据库 SELECT 1 及已启用的 MCP 传输生命周期; 全部就绪返回 200,否则返回 503,元数据库探测预算为2秒。MCP 关闭时标记为 disabled,不阻止就绪。返回结果不包含数据库地址、凭据或原始异常,禁止缓存。 就绪状态不等同于 OAuth、用户权限或真实工具调用成功;指定项目的业务库和时序库仍通过 带身份与 X-Project-Id 的 GET /api/v1/projects/current/database-health 检查。

常用命令

外围接入样板是独立进程,复用 PostgreSQL,不自动建表;启动、授权边界和契约见 外围样板说明。 外围样板提供 synthetic 测试工单和测试数据的版本化 CRUD;工单经同步器投影为 workbench.operational_tasks 中的外围来源任务。固定演示时窗和造数方式见 合成样本说明,运行态读取边界见 工作台运行态说明。这些数据不代表现场事实,也不会触发设备控制。

conda run -n server python -m pytest tests -q
conda run -n server python scripts/run_server.py
docker build -t tjwater-server:local .
docker compose -f infra/docker/docker-compose.yml config
  • pytest:运行自动化测试。
  • scripts/run_server.py:使用项目脚本启动服务。
  • docker build:构建后端镜像。
  • docker compose config:检查 compose 配置和变量展开。

开发规范

  • Python 文件、函数、变量、Pydantic 字段、JSON body 字段和 query 参数使用 snake_case。
  • Python 类和 Pydantic 模型使用 PascalCase。
  • 新 HTTP 路径使用 kebab-case,例如 /api/v1/pressure-status/analyze。
  • 优先复用现有 FastAPI/service/repository 边界。
  • 不要把临时数据、数据库 dump、日志或本地运行产物纳入提交。

项目数据库路由

项目级 REST 请求通过 X-Project-Id 解析元数据中的数据库配置:

  • biz_data DSN 用于管网业务数据。每个物理业务库使用同名 _template 数据库,通过逻辑订阅只同步 network schema;模拟临时库从该项目模板克隆。WNDB_SCHEMA_TEMPLATE_DB_NAME(当前为 tjwater_v2_schema_template)仅用于创建空业务库和 INP 导入暂存库。
  • iot_data DSN 用于 TimescaleDB,始终使用元数据配置的完整 DSN,不再从项目代码推导数据库名。
  • 元数据、业务库和 TimescaleDB 可以部署在同一主机,也可以分别部署。

在线重算会原子替换一个时刻的节点、管段基线。历史分块已经压缩时,写入事务使用 TIMESCALEDB_REALTIME_MAX_DECOMPRESSED_TUPLES 设置解压预算,默认100万条;配置必须 为正整数,不允许0。该设置仅在实时快照写入事务内生效,不改变数据库全局设置或普通读取。 预算按需根据受影响压缩批次的规模调整,超过预算仍会失败并回滚当前快照;此前完成的其他 时刻不会一起回滚。同步、异步及单表批量快照入口使用同一预算。

压缩写入回归位于 tests/integration/test_realtime_compression.py;仅在设置 REALTIME_COMPRESSION_TEST_DSN 时执行,并且只接受库名以 tjw_test_realtime_ 开头的 独立可丢弃数据库。测试会创建和删除该库内的 realtime schema,禁止指向项目数据库。

完整新建供水项目使用 POST /api/v1/admin/project-provisions,以 multipart/form-data 同时提交 name、小写 code、可选的 description、gs_workspace、map_zoom 和 INP file。工作流会按顺序完成:

  1. EPANET 校验 INP,并从空结构模板创建业务库、导入模型;
  2. 创建同名 _template,复制 32 张 network 表并建立逻辑订阅;
  3. 从 TIMESCALEDB_SCHEMA_TEMPLATE_DB_NAME 创建空时序库;
  4. 创建 GeoServer 工作空间、PostGIS 数据存储和 7 个 GIS 图层,将客户端缓存设为 GEOSERVER_CLIENT_CACHE_SECONDS;
  5. 最后在一个元数据事务中写入项目、两条加密数据库路由和创建者成员关系,并将项目设为 active。

基础设施任一步失败时按 GeoServer、时序库、管网模板、业务库的逆序清理;元数据提交失败也执行同样清理。旧 POST /admin/projects 仅保留给已经由外部流程创建好的资源登记使用,并已标记为 deprecated。

使用模板复制或临时方案库的模拟功能时,biz_data 账号必须具备数据库创建和删除权限;只有显式删除项目时才会终止该项目的现有数据库会话,普通复制不会主动中断复制源会话。

奉贤项目的原始 GIS 与水质监测点使用独立脚本维护。导入脚本读取两份交付目录并写入项目 BizDB;水质脚本调用现有灵敏度分析服务生成 50 个监测点;发布脚本创建 10 个项目图层并刷新 GeoServer 缓存:

conda run -n server python scripts/import_fengxian_gis.py --database tjwater_v2
conda run -n server python scripts/generate_fengxian_water_quality_points.py --project tjwater_v2
conda run -n server python scripts/publish_fengxian_map_layers.py --database tjwater_v2 --workspace tjwater_next

发布命令需要配置 GEOSERVER_URL、GEOSERVER_USERNAME 和 GEOSERVER_PASSWORD。其中 7 个基础管网图层仍由项目供应流程创建,奉贤发布脚本追加 9 个原始 GIS 图层和 1 个水质监测点图层。

测试与发布

提交前根据改动范围运行最小有效测试:

conda run -n server python -m pytest tests/unit tests/auth -q

发布镜像前建议运行:

docker build -t tjwater-server:local .

Gitea 包工作流位于 .gitea/workflows/package.yml,通常由 tag 触发构建、推送镜像并通知部署 webhook。

安全规则

不要提交 .env、客户数据、数据库 dump、日志、生成缓存、db_inp/、temp/、data/ 或本地密钥。CI/CD 凭据应放在 Gitea secrets 和仓库变量中。

产品 MCP 查询

Server 可选启用 MCP 2026-07-28 的25项项目查询及10项受控分析,默认关闭。它使用专用 OAuth resource Bearer、宿主绑定上下文及现有项目/任务权限,调查查询返回前持久化证据。启用需更新依赖、应用项目 SQL 迁移和配置 Keycloak token exchange;这些生产操作尚未执行。详见 实施与启用 和 协议/旧 CLI 能力对照。