feat(wordcloud): 收口在途开发(布局/存储/前端)+ R4 WCD 生产任务(jobs wcd_file)与生产订单列表

This commit is contained in:
2026-08-13 14:22:48 +08:00
parent 1d17b5e20d
commit e518540235
32 changed files with 3525 additions and 592 deletions
+173
View File
@@ -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。