refactor(db)!: adopt project-routed pooled databases
Reorganize WNDB by responsibility and remove legacy scheme endpoints.\n\nRoute analysis and time-series access through project pools, preserve transactional realtime replacement, and refresh GIS materialized views after writes.\n\nAdd database architecture documentation, live pooling coverage, API contract updates, and executable container verification.\n\nBREAKING CHANGE: legacy scheme APIs and flat app.native.wndb module imports are removed.
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
# WNDB 文件结构说明
|
||||
|
||||
本文记录 2026-08-25 完成的 WNDB 目录与命令结构重构。检查对象是当前代码,不以旧 SQL 脚本或历史目录为依据。
|
||||
|
||||
## 结论
|
||||
|
||||
当前结构适合继续维护。WNDB 已按连接基础设施、管网模型、GIS、INP 和命令执行分组,原来的编号文件名、根目录聚合门面和星号导入已经移除。WDA、SCADA 资产查询和测压点选址也已离开底层模型目录。
|
||||
|
||||
本次调整了代码文件、导入关系、命令分派和 WNDB 内部命令对象,没有改变 HTTP 接口。历史撤销日志已从数据库中移除,内部接口不再保留无效的兼容字段。真实库回归时发现五张明细表错误地把局部顺序号设成全局主键,已在 `tjwater_next` 中改为父对象 ID 与 `sequence_no` 的复合主键。
|
||||
|
||||
## 当前目录
|
||||
|
||||
```text
|
||||
app/native/wndb/
|
||||
├── __init__.py
|
||||
├── core/
|
||||
│ ├── connection.py
|
||||
│ ├── database.py
|
||||
│ └── projects.py
|
||||
├── model/
|
||||
│ ├── elements.py
|
||||
│ ├── junctions.py
|
||||
│ ├── reservoirs.py
|
||||
│ ├── tanks.py
|
||||
│ ├── pipes.py
|
||||
│ ├── pumps.py
|
||||
│ ├── valves.py
|
||||
│ ├── patterns.py
|
||||
│ ├── curves.py
|
||||
│ ├── options.py
|
||||
│ └── 其他 EPANET 模型模块
|
||||
├── gis/
|
||||
│ ├── coordinates.py
|
||||
│ ├── vertices.py
|
||||
│ ├── labels.py
|
||||
│ ├── backdrop.py
|
||||
│ ├── regions.py
|
||||
│ └── region_geometry.py
|
||||
├── inp/
|
||||
│ ├── sections.py
|
||||
│ ├── importer.py
|
||||
│ └── exporter.py
|
||||
└── commands/
|
||||
├── api.py
|
||||
├── cascade.py
|
||||
└── executor.py
|
||||
```
|
||||
|
||||
目录内共有 47 个 Python 文件,约 7,100 行。`app/native/wndb/__init__.py` 只保留包说明,不再统一导出所有函数。调用方需要从具体职责模块导入,依赖来源可以直接从文件头确认。
|
||||
|
||||
## 各目录的职责
|
||||
|
||||
### core:连接、事务和数据库基础能力
|
||||
|
||||
`connection.py` 管理项目连接池、管理连接池和项目事务上下文。连接池按路由后的 DSN 复用,并限制缓存规模。
|
||||
|
||||
`database.py` 提供 `ChangeSet`、`DatabaseCommand`、参数化查询和物化视图刷新。`DatabaseCommand` 只保存待执行的 SQL 和执行成功后返回给调用方的变更列表,不再生成或保存撤销 SQL。模型直接修改时按需刷新视图;批量命令在外层事务提交后只刷新一次。物化视图保留模型坐标 `x`、`y`,同时将供 GeoServer 使用的 `geom` 转换为 `EPSG:3857`,WNDB 查询不会把发布坐标误当成模型坐标。
|
||||
|
||||
`projects.py` 只负责项目数据库的创建、复制、打开、关闭和删除,不再混入模型查询。
|
||||
|
||||
### model:管网模型和仿真配置
|
||||
|
||||
`model` 按业务实体命名,不再使用 `s2_junctions.py` 这类 INP 章节编号。节点、连接、模式、曲线、需求、规则和仿真设置都能从文件名直接定位。
|
||||
|
||||
每个实体模块保留三类紧密相关的函数:读取实体、生成并执行实体变更、转换该实体对应的一行或一段 INP 内容。完整文件的读取顺序、事务和项目生命周期由 `inp` 目录负责。因此,实体级编解码仍靠近实体定义,跨章节编排已经集中。
|
||||
|
||||
`elements.py` 保存节点、连接、模式、曲线和区域的通用类型判断及拓扑查询。它不再承担业务算法。
|
||||
|
||||
### gis:空间数据和区域几何
|
||||
|
||||
`coordinates.py`、`vertices.py`、`labels.py` 和 `backdrop.py` 对应原始 GIS 数据。`regions.py` 负责区域持久化,`region_geometry.py` 负责边界、凸包、膨胀和区域内元素查询。
|
||||
|
||||
管网实体修改会调用坐标 SQL 辅助函数,区域几何也会读取管网拓扑。这里存在明确的模型与 GIS 协作,但没有模块导入环。现阶段继续拆出抽象接口只会增加层级,没有实际收益。
|
||||
|
||||
### inp:文件级导入导出
|
||||
|
||||
`sections.py` 只保存 INP 章节名称和输出顺序。旧文件中混放的 `s1_title`、`s2_junction` 等命令类型常量已经移除。
|
||||
|
||||
`importer.py` 负责文件分段、导入顺序、项目事务、版本转换和导入后的物化视图刷新。`exporter.py` 负责按 EPANET 版本组织各章节并写出文件或 `ChangeSet`。
|
||||
|
||||
### commands:批量修改和级联关系
|
||||
|
||||
`api.py` 为级联删除和选项同步补齐命令元数据。`cascade.py` 将删除节点、连接、模式和曲线的请求展开为完整的关联修改。`executor.py` 在一个项目事务中执行展开后的命令。
|
||||
|
||||
元素命令分派已经由类型到处理函数的显式注册表实现。新增元素时,只需把受支持的新增、修改或删除处理函数登记到对应注册表。没有处理函数的命令保持空操作,行为与改造前一致。
|
||||
|
||||
### 命令执行与事务
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
REQUEST[ChangeSet 请求]
|
||||
EXPAND[展开级联修改]
|
||||
BUILD[实体模块生成 DatabaseCommand]
|
||||
EXECUTE[执行 SQL]
|
||||
RESULT[返回 ChangeSet]
|
||||
COMMIT[提交项目事务]
|
||||
REFRESH[刷新物化视图]
|
||||
|
||||
REQUEST --> EXPAND --> BUILD --> EXECUTE --> RESULT
|
||||
EXECUTE --> COMMIT --> REFRESH
|
||||
```
|
||||
|
||||
实体模块根据请求生成 `DatabaseCommand`,其中 `sql` 是要执行的语句,`changes` 是成功后的变更结果。批量命令先在同一个项目事务中展开级联关系,再依次执行 SQL;任何一步失败都会回滚整个事务。事务提交后统一刷新物化视图,避免一次批量修改触发多次刷新。直接调用单个实体修改时,如果当前没有外层项目事务,则由 `execute_command` 完成提交并按影响范围刷新视图。
|
||||
|
||||
旧实现中的 `DbChangeSet` 同时保存执行和撤销两套 SQL、两套变更结果,但数据库已经不再提供 operation 或 snapshot 撤销日志,这些字段没有消费者。当前代码已经删除 `undo_sql`、`undo_cs` 及各实体模块中的撤销 SQL 构造,也删除了只为撤销结果读取旧记录的查询和辅助方法。局部修改仍会读取一次当前记录,用于补齐请求中未提供的字段;这类读取属于更新语义,不是撤销机制。
|
||||
|
||||
## WNDB 之外的业务代码
|
||||
|
||||
以下代码不再放在 `app/native/wndb`:
|
||||
|
||||
| 职责 | 当前路径 | 原因 |
|
||||
| --- | --- | --- |
|
||||
| 用水量分配计算 | `app/algorithms/water_demand/` | 属于业务算法,WNDB 只提供节点、需求和区域查询 |
|
||||
| SCADA 资产查询 | `app/infra/db/postgresql/scada_assets.py` | 对应 `asset.scada_devices` 的 PostgreSQL 仓储 |
|
||||
| 测压点选址结果 | `app/infra/db/postgresql/sensor_placement.py` | 对应 `analysis.runs` 和 `analysis.results` 的仓储 |
|
||||
| 服务组合入口 | `app/services/tjnetwork.py` | 组合 WNDB、EPANET 和业务仓储,供接口与算法层调用 |
|
||||
|
||||
`tjnetwork.py` 从约 995 行缩减到约 320 行。它不再通过 WNDB 根包获得全部函数,只显式导入当前服务使用的能力。过时的 `scripts/test_tjnetwork.py` 依赖已移除的 operation、snapshot、DMA 和旧 SCADA API,已经一并删除。
|
||||
|
||||
## 依赖方向
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
API[HTTP 接口与业务服务]
|
||||
SERVICE[services.tjnetwork]
|
||||
ALGORITHM[业务算法]
|
||||
REPOSITORY[PostgreSQL 业务仓储]
|
||||
COMMANDS[wndb.commands]
|
||||
INP[wndb.inp]
|
||||
MODEL[wndb.model]
|
||||
GIS[wndb.gis]
|
||||
CORE[wndb.core]
|
||||
DB[(项目业务数据库)]
|
||||
|
||||
API --> SERVICE
|
||||
API --> ALGORITHM
|
||||
API --> REPOSITORY
|
||||
SERVICE --> COMMANDS
|
||||
SERVICE --> INP
|
||||
SERVICE --> MODEL
|
||||
SERVICE --> GIS
|
||||
SERVICE --> REPOSITORY
|
||||
COMMANDS --> MODEL
|
||||
COMMANDS --> GIS
|
||||
COMMANDS --> CORE
|
||||
INP --> MODEL
|
||||
INP --> GIS
|
||||
INP --> CORE
|
||||
MODEL --> CORE
|
||||
GIS --> CORE
|
||||
MODEL --> GIS
|
||||
GIS --> MODEL
|
||||
CORE --> DB
|
||||
REPOSITORY --> DB
|
||||
```
|
||||
|
||||
WNDB 根包不再作为依赖汇聚点。上层若只需要管道查询,应直接依赖 `model.pipes`;需要区域几何时依赖 `gis.region_geometry`;需要项目连接时依赖 `core.connection`。
|
||||
|
||||
## 仍需留意的文件规模
|
||||
|
||||
`importer.py` 和 `region_geometry.py` 行数较多,但函数仍围绕单一职责。只有在继续增加 INP 格式或区域算法时,才需要分别拆出版本转换器或边界算法模块。目前没有必要为了控制文件行数继续分层。
|
||||
|
||||
## 验证结果
|
||||
|
||||
- 本地 conda 环境全量测试:239 项通过,10 项按条件跳过。
|
||||
- Docker 镜像构建成功,镜像内全量测试结果一致。
|
||||
- `tjwater_next` 真实数据库测试:8 项通过,覆盖业务库和时序库并发借用、嵌套事务回滚、分析运行生命周期、恶意标识符转义、五张明细表的复合主键,以及 WNDB pattern 增删改、级联解除需求关联和整体回滚。
|
||||
- Python 编译、未使用导入扫描、撤销字段残留扫描和 `git diff --check` 均通过。
|
||||
Reference in New Issue
Block a user