Files
wordcloud/docs/DESIGN_DATA_STORAGE_PLAN.md
T

174 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 存储与数据库重构方案(规划)
> 状态:第一阶段部分已落地(任务元数据落 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。