109 lines
4.5 KiB
Markdown
109 lines
4.5 KiB
Markdown
# TJWaterServerBinary 内部后端
|
||
|
||
`TJWaterServerBinary` 是 TJWater 内部版 Python 后端,基于 FastAPI 提供认证、项目、管网、模拟、爆管、漏损、SCADA 和地图服务集成能力。该仓库用于内部开发和完整功能维护。
|
||
|
||
## 技术栈
|
||
|
||
- Python 3.12
|
||
- FastAPI / Uvicorn
|
||
- Pydantic / SQLAlchemy / psycopg
|
||
- PostgreSQL、PostGIS、TimescaleDB
|
||
- WNTR、EPANET、Cython、科学计算与空间分析依赖
|
||
- pytest
|
||
|
||
## 目录结构
|
||
|
||
```text
|
||
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 环境:
|
||
|
||
```bash
|
||
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
|
||
```
|
||
|
||
如需要进入环境:
|
||
|
||
```bash
|
||
conda activate server
|
||
```
|
||
|
||
## 常用命令
|
||
|
||
```bash
|
||
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 可以部署在同一主机,也可以分别部署。
|
||
|
||
完整新建供水项目使用 `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` 账号必须具备数据库创建和删除权限;只有显式删除项目时才会终止该项目的现有数据库会话,普通复制不会主动中断复制源会话。
|
||
|
||
## 测试与发布
|
||
|
||
提交前根据改动范围运行最小有效测试:
|
||
|
||
```bash
|
||
conda run -n server python -m pytest tests/unit tests/auth -q
|
||
```
|
||
|
||
发布镜像前建议运行:
|
||
|
||
```bash
|
||
docker build -t tjwater-server:local .
|
||
```
|
||
|
||
Gitea 包工作流位于 `.gitea/workflows/package.yml`,通常由 tag 触发构建、推送镜像并通知部署 webhook。
|
||
|
||
## 安全规则
|
||
|
||
不要提交 `.env`、客户数据、数据库 dump、日志、生成缓存、`db_inp/`、`temp/`、`data/` 或本地密钥。CI/CD 凭据应放在 Gitea secrets 和仓库变量中。
|