feat(wordcloud): 收口在途开发(布局/存储/前端)+ R4 WCD 生产任务(jobs wcd_file)与生产订单列表
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
# 存储与数据库重构方案(规划)
|
||||
|
||||
> 状态:第一阶段部分已落地(任务元数据落 SQLite、任务清理审计、素材 sha256)。
|
||||
> 目的:后端当前仍以“内存 + 文件 + 任务级 SQLite + meta.json”为主要存储方式。本文档规划后续迁移到 PostgreSQL 元数据库,并优化任务生命周期和贴纸持久化。
|
||||
|
||||
## 1. 当前现状
|
||||
|
||||
| 数据 | 当前存储 | 问题 |
|
||||
|---|---|---|
|
||||
| 任务状态 / 事件 | `JobManager._jobs` 仅存内存 | 重启服务后任务记录丢失 |
|
||||
| 任务输入 / 输出 | `backend/service_workspace/{job_id}` | 提交任务即建目录,未完成或被放弃的任务会遗留文件 |
|
||||
| 词云坐标结果 | 每个任务生成一个 `word_locations.db`(SQLite) | 每个任务自带一份 SQLite 文件,查询分散 |
|
||||
| 贴纸素材 | `backend/service_assets/asset_xxx/asset.svg` + `meta.json` | 素材元数据不是数据库,tint 等前端信息还依赖 localStorage |
|
||||
| 设计模板 / 工程 | `service_design_templates` / `service_projects` 目录 + JSON | 模板和工程之间缺少数据库关联 |
|
||||
| 画布文档 | 前端 localStorage | 无法跨设备,也无法作为后端权威数据 |
|
||||
|
||||
注意:当前不能认为系统已经在使用 PostgreSQL。代码中出现的 `*.db` 是词云算法自己写的 SQLite 结果文件,例如 `backend/core/pipeline.py` 的 `word_locations` 表。
|
||||
|
||||
## 2. 目标架构
|
||||
|
||||
整体原则:
|
||||
|
||||
- **文件继续存文件系统或对象存储**(SVG / PNG / 遮罩 / Excel / 字体)。
|
||||
- **业务元数据和引用关系存 PostgreSQL**。
|
||||
- 数据库保存路径引用,不保存大文件内容。
|
||||
|
||||
目标模型:
|
||||
|
||||
| 表 | 用途 | 说明 |
|
||||
|---|---|---|
|
||||
| `jobs` | 任务主表 | job_id、状态、参数 JSONB、产物引用、创建时间 |
|
||||
| `job_events` | 任务进度事件 | SSE 进度事件落库,服务重启后可恢复 |
|
||||
| `assets` | 贴纸 / 素材表 | 素材元数据、文件路径、来源 job、sha256、tint |
|
||||
| `design_documents` | 画布文档 | CanvasDocument JSONB,绑定模板/工程 |
|
||||
| `design_templates` | 模板 | 模板元数据 + 画布文档引用 |
|
||||
| `projects` | 工程 | 模板 + 画布文档 + 素材引用 |
|
||||
|
||||
### jobs 表字段建议
|
||||
|
||||
```text
|
||||
id uuid pk
|
||||
status text -- submitted/running/success/failed/cancelled
|
||||
stage text
|
||||
progress int
|
||||
message text
|
||||
params jsonb -- 用户提交的词云参数
|
||||
input_files jsonb -- mask/excel/font 引用
|
||||
artifacts jsonb -- png/svg/svg_stroke/db/metrics 路径或文件 id
|
||||
error text
|
||||
created_at timestamptz
|
||||
updated_at timestamptz
|
||||
retention_until timestamptz -- 清理时间
|
||||
```
|
||||
|
||||
### assets 表字段建议
|
||||
|
||||
```text
|
||||
id uuid pk
|
||||
name text
|
||||
type text -- wordcloud / upload / shape / reference
|
||||
mime_type text
|
||||
storage_key text -- 文件系统路径或对象存储 key
|
||||
width int
|
||||
height int
|
||||
file_size bigint
|
||||
sha256 text -- 用于导入去重
|
||||
source_job_id uuid nullable
|
||||
tint text nullable
|
||||
created_at timestamptz
|
||||
deleted_at timestamptz nullable
|
||||
```
|
||||
|
||||
## 3. 任务存储链路
|
||||
|
||||
现状是 `POST /api/jobs` 提交时直接创建 job 目录和保存上传文件。
|
||||
|
||||
目标改动:
|
||||
|
||||
1. `POST /api/jobs` 只写 `jobs` 表,状态为 `submitted` 或 `queued`。
|
||||
2. 上传文件先落到临时上传区,或延迟到进入 runner 前再落盘。
|
||||
3. runner 真正开始时才创建任务的 `input/` 和 `output/` 目录。
|
||||
4. 任务完成后把产物路径/文件 id 写入 `jobs.artifacts`。
|
||||
5. 增加后台清理任务:
|
||||
- 清理 `completed` 且未被贴纸/工程引用的任务文件。
|
||||
- 支持按 `retention_until` 保留最近结果。
|
||||
- 被用户导入为贴纸的任务文件可延长保留时间。
|
||||
|
||||
这样不会每次申请都攒下一堆用不上的目录和文件。
|
||||
|
||||
## 4. 贴纸持久化
|
||||
|
||||
贴纸在当前 `frontend/src/lib/stickerLibrary.ts` 中已经走后端 `POST /api/assets`,但元数据仍写在 `meta.json`,tint 还保存在 localStorage。
|
||||
|
||||
目标改动:
|
||||
|
||||
- `assets` 表作为贴纸唯一权威来源。
|
||||
- `POST /api/assets`:写文件系统 + 写 `assets` 表,返回 `asset_id`。
|
||||
- `GET /api/assets`:从数据库读取列表。
|
||||
- `PATCH /api/assets/{id}`:更新 tint、name 等元数据。
|
||||
- `DELETE /api/assets/{id}`:物理删除文件 + 记录,或软删除防止破坏设计文档引用。
|
||||
- `POST /api/assets/from-job/{job_id}`:沿用同一逻辑,写入 `source_job_id`。
|
||||
- 前端不再依赖 localStorage 保存贴纸 tint,加载和更新都走 API。
|
||||
|
||||
## 5. 画布文档与模板
|
||||
|
||||
当前画布保存在 localStorage,模板保存成目录 JSON。
|
||||
|
||||
目标改动:
|
||||
|
||||
- `design_documents` 保存 `CanvasDocument` JSONB。
|
||||
- 画布每次保存调用 `PUT /api/documents/{id}`。
|
||||
- `design_templates` 引用 `design_documents`,同时记录 `reference_asset_ids` 和封面图。
|
||||
- 后续实现画布导出导入时,导入包可直接写入 `design_documents`,并把包内素材批量写入 `assets` 表。
|
||||
|
||||
## 6. PostgreSQL 接入方式
|
||||
|
||||
建议:
|
||||
|
||||
- 引入 SQLAlchemy(或 asyncpg)作为数据库访问层。
|
||||
- 使用 Alembic 管理 migration。
|
||||
- 在 `docker-compose.yml` 增加 PostgreSQL 服务。
|
||||
- 通过环境变量注入 `DATABASE_URL`,本地开发和 Docker 使用不同配置。
|
||||
- 暂不把词云算法的 `word_locations` 表强制迁移到 PostgreSQL,可以保留 SQLite 作为任务内部产物,再通过导出接口把需要的布局结果写入 `jobs` 或独立布局表中。
|
||||
|
||||
## 7. 分阶段实施
|
||||
|
||||
### 阶段一:接入 PostgreSQL,先做贴纸和任务元数据(任务元数据已用 SQLite 先行落地)
|
||||
|
||||
- 建 `assets` / `jobs` / `job_events` 表。
|
||||
- `assets` 接口从文件 meta 迁移到 DB。
|
||||
- 提交任务仍可使用现有 runner,但把任务状态写入 DB。
|
||||
- 不改动词云算法核心。
|
||||
|
||||
### 阶段二:任务生命周期优化(清理审计已落地)
|
||||
|
||||
- `POST /api/jobs` 只记账,不提前建目录。
|
||||
- runner 开始前再落 input/output。
|
||||
- 增加 TTL 清理任务。
|
||||
- 任务列表、任务详情改为从 DB 查询。
|
||||
|
||||
### 阶段三:画布文档和导入包
|
||||
|
||||
- 建 `design_documents` / `design_templates` / `projects` 表。
|
||||
- 画布保存从 localStorage 改为后端文档接口。
|
||||
- `wcd` 导入导出包直接对接这些表。
|
||||
|
||||
## 8. 风险与注意点
|
||||
|
||||
- 现有任务接口依赖内存中的 `JobManager`,迁到 DB 后需要兼容 SSE 进度事件。
|
||||
- 文件迁移只能做增量:老素材目录可先保留,新写入走 DB。
|
||||
- 删除素材要检查 `design_documents` 引用,避免出现缺失贴纸。
|
||||
- tint 从前端 localStorage 迁移到 DB 时,需要兼容旧浏览器状态。
|
||||
|
||||
## 10. 已落地实现
|
||||
|
||||
- `backend/service/metadata_store.py`:SQLite 元数据 `jobs` / `job_events`。
|
||||
- `backend/service/job_manager.py`:任务状态和事件落库,服务重启可恢复。
|
||||
- `backend/service/storage.py`:任务目录占用、过期审计、可清理能力。
|
||||
- `backend/service/storage_metrics.py`:dry-run 指标和显式 `--apply` 清理。
|
||||
- `backend/service/app.py`:`GET /api/maintenance/storage-summary`。
|
||||
- `docs/DATA_STORAGE_OPTIMIZATION.md`:完整空间/效能指标。
|
||||
|
||||
> 注:当前项目没有接入 PostgreSQL。代码里的 `*.db` 是词云算法自己的 SQLite 结果文件;新加的 `service_metadata/app.db` 是业务元数据先行层。`jobs` / `job_events` 表结构设计上可平滑迁移到 PostgreSQL。
|
||||
|
||||
## 9. 相关文件参考
|
||||
|
||||
- `backend/service/app.py`:目前的任务、素材、模板 API。
|
||||
- `backend/service/job_manager.py`:内存中的任务状态。
|
||||
- `backend/service/storage.py`:任务目录创建。
|
||||
- `backend/service/runner.py`:任务运行与产物扫描。
|
||||
- `backend/core/pipeline.py`:词云结果 SQLite 写入。
|
||||
- `frontend/src/lib/stickerLibrary.ts`:前端贴纸库。
|
||||
- `docker-compose.yml`:服务编排,后续加 PostgreSQL。
|
||||
Reference in New Issue
Block a user