95 lines
6.6 KiB
Markdown
95 lines
6.6 KiB
Markdown
# 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 验证期数据与现网彻底隔离,不回迁;若验证后需并回主线,另行决策迁移口径。
|