Files
iboard/docs/V0.2/离线编辑模块/0.2.1实施方案.md
T

95 lines
6.6 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.
# 0.2.1 实施方案:PostgreSQL 迁移 + 任务模块离线编辑 (PowerSync)
| 项 | 内容 |
| --- | --- |
| 分支 | `dev-0.2.1`(worktree `iboard-dev-0.2.1`,独立临时分支,与 master / dev-0.2 隔离) |
| 日期 | 2026-10-25 |
| 依据 | [PowerSync可行性研究报告](./PowerSync可行性研究报告.md),按其 5.2.2 路线执行 |
| 目标 | 在现网应用与数据不受影响的前提下,验证任务模块离线编辑 + 联网后自动双向同步;数据库由 MariaDB 迁移至 PostgreSQL |
## 1. 已确认决策(2026-10-25 与需求方对齐)
| 决策点 | 结论 |
| --- | --- |
| 技术路线 | PowerSync 全链路(自部署 powersync-service) |
| 离线范围 | 仅任务模块(Project / ProjectMember / BoardColumn / Task / TaskMember / TaskTag);打卡、清单本阶段不纳入;新闻/指标/监控等时序域仅做普通缓存 |
| 客户端 | 先 Web / Windows 外壳(WebView2)跑通全链路;Android 真机后续验证 |
| 编号 | 项目短前缀由用户自拟(2~8 位,全局唯一);任务号 = 项目内自增整数,展示 `前缀-序号`;编号由服务端统一分配,离线创建的任务在同步定号前显示临时标识 |
| 初始数据 | 从现网 MariaDB 只读快照导出并转换导入新 PG;0.2.1 期间产生的新数据不回写现网 |
| 端口 | Web/API 13001、PowerSync WebSocket 13002、PG 仅容器内网(调试绑 127.0.0.1:15432) |
| 部署 | 源码上传 baihu `/app/iboard-0.2.1`,服务器上 `docker compose build`;不使用原 CI/CD |
| 现网保护 | `/app/iboard`、宿主 3306 MySQL、3001 端口、原 CI/CD 一律不使用(快照导出仅 SELECT) |
| 磁盘 | 允许在 baihu 执行 docker 悬空镜像/构建缓存的安全清理(磁盘仅剩 9.9G) |
## 2. 目标架构
```
[Web / Tauri WebView2]
React + @powersync/react
本地 WASM SQLite (OPFS 持久化)
│ 离线: 直接读写本地库; 写操作进入 upload queue
│ 联网: 批量 POST 上行到 Express API (按 uuid 幂等 upsert)
▼
[iboard-0.2.1 Express :13001] ── Prisma (adapter-pg) ──┐
+ /api/powersync/token (为登录用户签发同步 JWT) ▼
[PostgreSQL 容器] (wal_level=logical)
▲ 逻辑复制 (publication + replication slot)
[powersync-service :13002] ── Sync Rules: 任务域 6 表 + User 只读引用, 按 ProjectMember 过滤
```
- 写路径:客户端本地写 → upload queue → 上行 API → Prisma 写 PG → 逻辑复制捕获 → 广播各端;
- 读路径:任务模块页面全部改读本地 SQLite(@powersync/react 响应式查询),其余页面维持 axios REST;
- 认证:复用现有 jsonwebtoken 体系,新增 `/api/powersync/token` 签发 PowerSync 校验的 JWT。
## 3. 数据模型改造(原则:只增不改)
采用报告 3.2 中的「新增 uuid 列 + 应用层幂等 upsert」选项,不做全表主键 UUID 化:外键关系全部保留,存量数据迁移风险最小。
- 任务域 6 表各加 `uuid varchar(36) unique`(客户端创建时生成;存量行导入时回填);
- `Project` 加 `code varchar(8) unique`(用户自拟短前缀;存量项目导入时回填自动码,后续可改);
- `Task` 加 `number int`,`@@unique([projectId, number])`(服务端按项目 max+1 分配;离线创建的任务上行时定号,本地未定号行显示临时标识);
- 主键仍为自增 Int,业务外键不动;客户端上行一律以 uuid 引用父子行,服务端解析为内部 id;
- Prisma datasource: `mysql` → `postgresql`;本分支重建基线迁移(旧 MySQL 迁移文件移除,历史保留在 git)。
## 4. 同步与冲突
- Sync Rules 仅下发任务域 6 表 + `User`(展示名称/头像用),按 `ProjectMember.userId = auth.parameters.userId` 过滤项目可见性;时序/监控/米家等表不纳入;
- 上行:`POST /api/powersync/upload` 批处理客户端 CRUD 操作,按 uuid 幂等 upsert,更新时以服务端时间戳做 LWW 仲裁;
- 冲突:字段级 LWW 为主;`BoardColumn.sortOrder` / `Task.sortOrder` 由服务端重排仲裁;并发唯一冲突(项目前缀、看板列名)返回明确错误,客户端提示重试;
- `Task.number` / `Project.code` 由服务端唯一分配,多端并发下天然无冲突。
## 5. 部署拓扑(baihu `/app/iboard-0.2.1`)
docker compose 三服务:
| 服务 | 镜像 | 端口 | 说明 |
| --- | --- | --- | --- |
| `pg-021` | postgres:16-alpine | 仅容器内网 | `wal_level=logical`;数据卷 `./data/pg` |
| `powersync-021` | powersync 官方镜像 | 13002 对外 | 连接 PG 逻辑复制 + WebSocket 下发 |
| `app-021` | 本仓库 Dockerfile 构建 | 13001 对外 | `OTA_PUBLIC_BASE=http://bh.vps.honor3:13001` |
- 环境变量由 compose 注入:`DATABASE_URL`(指向 pg-021)、`JWT_SECRET`(0.2.1 独立新设)、`PORT=13001`;
- 0.2.1 容器内 cron/米家调度预计无凭证或产生重复外呼,部署时以环境开关关闭(实现于 M4)。
## 6. 数据迁移(一次性)
1. 在 baihu 上用仓库自带 `mariadb` 驱动以只读 SQL 从宿主 MySQL(3306) 导出全表 JSON(仅 SELECT);
2. 转换:回填 uuid / `Project.code`(按名称自动生成,可后改)/ `Task.number`(按项目内 createdAt 顺序);时间字段转 PG 时间戳;
3. PG 侧先 `prisma migrate deploy` 建基线表,再执行 ETL 写入;
4. 校验:逐表行数比对 + 抽样字段比对,输出核对报告。
## 7. 里程碑
1. **M1** schema/适配层切 PG(本提交):schema 字段、db.js 适配器、基线迁移重建、本地 `prisma generate` 通过;
2. **M2** 服务端:powersync token 端点、upload 幂等上行端点、任务域路由幂等化与编号分配逻辑;
3. **M3** 前端:任务模块数据层切 PowerSync(本地库 + useQuery + 上传队列),桌面端联调;
4. **M4** compose 编排 + ETL 导数 + baihu 部署,端口/现网隔离验证;
5. **M5** 离线-联网闭环验证(断网编辑 → 恢复自动同步 → 多端一致),Android 真机评估。
## 8. 开放问题 / 风险
- powersync-service 的元数据存储(bucket storage)对 MongoDB 的依赖需在部署阶段核实;若当前版本不支持用 PG 存元数据,则加一个 mongo 容器;
- Android System WebView 的 OPFS/WASM SQLite 兼容性(M5 评估,先桌面);
- 项目前缀全局唯一在多端并发下的冲突提示体验(上行返回结构化错误码);
- 0.2.1 验证期数据与现网彻底隔离,不回迁;若验证后需并回主线,另行决策迁移口径。