Files
iboard/docs/V0.2/离线编辑模块/PowerSync可行性研究报告.md
T
jif2.zhang 74e1e7dd13
Docker Build and Push / build-image (push) Successful in 1m25s
feat(V0.2): 标题30字+智能拆分 / 时间标记 MM-dd / 时间词前缀 (T-TK-14~16)
- 标题上限收紧至 30 字 (服务端校验+详情编辑框); 快速添加输入框
  放宽到 200 字: 超长时在 30 字内分隔符处截断为标题, 完整原文进描述
- Task.markDate (DateTime, 迁移 20261025120000): 详情页 DatePicker
  选择/清除, 列表行与看板卡显示 MM-dd 小标签
- 快速添加时间词前缀: 今天/明天/后天/本周/下周/本月/下月 开头
  (后跟分隔符) 自动设为时间标记并移出标题; 本周=本周日, 本月=月末
- 需求/功能/数据库设计文档同步更新 T-TK-14~16 与 Task 表字段
2026-10-25 11:47:44 +08:00

128 lines
10 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.
# 基于 PowerSync 的离线编辑可行性研究报告
| 项 | 内容 |
| --- | --- |
| 版本 | V0.2 |
| 日期 | 2026-10-25 |
| 评估对象 | PowerSync(powersync.com,开源 self-hosted + 云服务) |
| 评估目标 | 项目离线操作(本地编辑)+ 联网后自动同步 |
| 结论(TL;DR) | **技术上可行,但落地成本高、风险中高。不建议全量接入;若确需离线,建议仅对「打卡 / 清单 / 任务」等用户编辑域做局部接入,且需要先解决 MariaDB 兼容与主键策略两个前置问题。** |
---
## 1. 项目现状约束(评估输入)
结合代码库(`package.json`、`prisma/schema.prisma`、`server/index.js`)梳理:
1. **前端**:React 18 SPA(antd-mobile),通过 axios 调 `/api/*` REST 接口;`src/api`、`src/hooks`、`src/pages` 均以"请求 → state → 渲染"模式组织,无任何本地持久化数据层。
2. **桌面/移动端**:Tauri 2(Windows WebView2 桌面 + Android System WebView),意味着前端运行在 WebView 内,浏览器类 SDK 是候选。
3. **后端**:Express + Prisma,数据库为 **MariaDB / MySQL**(`provider = "mysql"`)。
4. **认证**:自签 JWT(jsonwebtoken),登录接口在 `/api/auth`。
5. **写路径**:全部业务写操作走 REST(打卡、清单、任务模块);同时存在大量**服务端定时写入**(cron:新闻、指标、监控、米家采样等,见 `server/cron.js`)。
6. **数据模型**:约 25 张表,主键全部为 `Int @id @default(autoincrement())` 自增整数,多表带复合唯一约束(如 `CheckIn @@unique([habitId, date, seq])`)。
7. **数据体量特征**:两类数据并存——
- **用户编辑域**(Habit / CheckIn / CheckList* / 任务模块 10 张表):冲突敏感、离线价值高;
- **服务端只读时序域**(News / Indicator / ServerNodeHistory / MihomeEnv* 等):append-only、量大、离线价值中等(缓存即可满足)。
---
## 2. PowerSync 是什么、怎么工作
- 架构:客户端本地 **SQLite**(Web 端为 WASM SQLite,存 OPFS/IndexedDB)↔ **PowerSync Service**(self-hosted 开源组件或云服务)↔ 源数据库。服务端通过 **逻辑复制/变更流** 捕获源库写入,按 **Sync Rules** 定义的下推子集同步到每个客户端的本地 SQLite。
- 写路径(官方推荐模式):客户端离线写本地 SQLite → 进入 **upload queue** → 联网后由前端把变更批量 POST 到**现有后端 API** → 后端用原有方式(本项目即 Prisma)写库 → 变更流捕获 → 广播回各端。
- 认证:客户端持后端签发的 JWT 连接同步服务;PowerSync 只做校验,不签发(可复用现有 jsonwebtoken 体系)。
- 服务端直写的表(cron 产生)也能被变更流捕获并下推,不需要改造写入方。
参考:[PowerSync Service(GitHub)](https://github.com/powersync-ja/powersync-service)、[源数据库支持](https://docs.powersync.com/configuration/source-db/setup)。
---
## 3. 逐项可行性分析
### 3.1 数据库兼容性 —— ⚠️ 主要风险点
- PowerSync 对源库支持:**PostgreSQL(GA)**、MongoDB、SQL Server;**MySQL 仍处于 Beta**(基于 binlog 复制,见 [MySQL Beta 公告](https://releases.powersync.com/announcements/mysql-backend-database-support-has-reached-beta)、[Alpha 公告](https://releases.powersync.com/announcements/announcing-mysql-as-a-source-database-alpha))。
- 本项目用的是 **MariaDB**。MariaDB 的 binlog 格式与 MySQL 8 有差异(GTID、行事件细节),PowerSync MySQL 插件(@powersync/mysql-zongji 系)对 MariaDB **没有官方兼容承诺,需要实测验证**,很可能踩坑。
- **结论**:要么实测 MariaDB + MySQL-beta 通路(风险高),要么把数据库迁到 PostgreSQL(PowerSync 最成熟路径,Prisma 迁移成本可控但涉及全部表和线上数据)。这是"能不能用"的第一道门槛。
### 3.2 数据模型适配 —— 改造成本大
- PowerSync Sync Rules 要求同步表有稳定的行标识,**强烈建议 UUID 文本主键**;而本项目全部是自增整数主键,且客户端离线创建记录时无法预知自增 id。
- 离线创建的通用解法:主键改为客户端生成的 UUID(`char(36)`),或新增 `uuid` 列 + 应用层幂等 upsert。对用户编辑域的 10 余张表意味着**一次不小的 schema 迁移 + 全部相关路由改造**(迁移原则"只增不改"仍可遵守,但外键列类型变更工作量大)。
- `DateTime`、`Json` 类型可映射(客户端以 ISO 文本/JSON 文本存储),但 `BigInt`(监控表)在 JS 端需按文本处理,注意精度。
- 复合唯一约束(`CheckIn(habitId,date,seq)`、`BoardColumn(projectId,name)` 等)在离线多端并发下会冲突,需在 upload 处理端路由里做服务端仲裁(如 seq 重排、重名加后缀),现有路由大多不具备幂等/仲裁语义。
### 3.3 写路径(离线编辑 + 上行同步)—— 模式契合,但需逐路由改造
- PowerSync 的 upload-queue → 后端 API 模式与现有 Express 架构**天然契合**:不需要后端暴露直接写库的通口,各业务路由补成"接收客户端 UUID + 幂等 upsert"即可。
- 打卡/清单/任务的路由数量约 3 个 router 文件(checkin / checklists / projects / tasks),逐个改造为幂等是可控的。
- 服务端 cron 写入的表(新闻/指标/监控/米家)无需改造写入方,只需在 Sync Rules 里定义是否下推。
### 3.4 读路径与前端数据层 —— 全面前重写
这是**工作量最大**的部分:
- 现有 `src/api` + axios + useEffect 模式必须替换为 PowerSync 本地 SQLite 查询 + `@powersync/react` 的响应式 hooks(useQuery 等),否则离线读不到数据。
- 涉及 `src/pages` 下全部用户编辑域页面(checkin、task),以及若要离线浏览还需覆盖 news/macro/monitor 的只读缓存页。
- 工作量量级:相当于把前端数据层重构一遍;可与"离线只读缓存(HTTP 缓存)"分层实施以降低风险。
### 3.5 客户端运行环境 —— 大体可行,Android 需验证
- **浏览器 / Tauri 桌面(WebView2)**:PowerSync Web SDK(WASM SQLite + OPFS)在 Chromium 系 WebView 已被官方支持,可行。
- **Tauri Android(System WebView)**:WASM SQLite 性能与 OPFS 在部分国产/旧版 WebView 上存在兼容性风险,需真机验证;备选方案是封装原生 SQLite(官方 Capacitor 插件思路可借鉴,但 Tauri 无官方插件,需自研 Rust 命令桥接,成本额外增加)。
- 时序大表(ServerNodeHistory 每分钟一条、MihomeEnv*)不建议纳入同步——Sync Rules 需做时间窗过滤(如仅近 7 天),否则客户端存储和同步流量都会失控。
### 3.6 认证与部署 —— 可行
- JWT 可复用:新增一个 `/api/powersync/token` 端点为已登录用户签发 PowerSync 接受的 token,改造小。
- 部署:self-hosted 需在现有 Express 之外多跑一个 powersync-service 进程(含 Mongo 存储元数据或云实例),并暴露 WebSocket 端口;或使用 PowerSync Cloud。运维面增加一个组件。
### 3.7 冲突解决
- PowerSync 本身不做自动合并,只提供上传队列与冲突回调;对"最后写入胜出"友好的字段(清单勾选、任务标题/状态)默认策略够用;对 `CheckIn.seq`、`BoardColumn.sortOrder` 这类"位置/序号型"数据需要自定义仲裁逻辑(上传端或同步流中处理),设计上可解,但要专门做。
---
## 4. 风险与成本汇总
| # | 风险/成本项 | 等级 | 说明 |
| --- | --- | --- | --- |
| 1 | MariaDB 兼容性未验证,MySQL 支持仅 Beta | 高 | 很可能需要迁移 PostgreSQL |
| 2 | 前端数据层全面重构(axios → 本地 SQLite 查询) | 高 | 涉及所有相关页面 |
| 3 | 用户编辑域主键整数自增 → UUID 迁移 | 中高 | schema + 路由幂等改造 |
| 4 | 复合唯一约束的离线冲突仲裁 | 中 | CheckIn.seq、列名、排序等 |
| 5 | Android WebView WASM SQLite/OPFS 兼容 | 中 | 需真机验证 |
| 6 | 新增 self-hosted 组件的运维 | 中 | 多一个常驻服务 |
| 7 | 时序大表同步范围控制 | 低 | Sync Rules 时间窗过滤即可 |
对照收益:真正需要离线**编辑**的只有打卡 / 清单 / 任务三个域(数据量小、单用户为主、冲突场景有限);其余域离线**只读缓存**即可满足。
---
## 5. 结论与建议
### 5.1 结论
**可行,但不建议以"全项目接入 PowerSync"的方式落地。** PowerSync 的同步模型与项目的 Express API 写路径契合、认证可复用、桌面端可行;但 MariaDB/MySQL-beta 兼容、整数自增主键、前端数据层全面重构三座大山使总成本明显高于当前阶段的收益。
### 5.2 建议(按优先序)
1. **首选(低成本方案)**:不引入 PowerSync,为用户编辑域实现轻量离线队列——前端把写请求落到 localStorage/IndexedDB 待发队列(含客户端生成的 UUID),联网后重放到现有 REST API(路由补幂等 upsert);只读页用 HTTP 缓存 + SW。可覆盖约 80% 的离线诉求,改动局限在 `src/api` 层与少量路由。
2. **若决定采用 PowerSync**:
- 前置 1:源库迁移 PostgreSQL(避开 MySQL Beta + MariaDB 兼容雷区);
- 前置 2:仅将用户编辑域(Habit/CheckIn/CheckList*/任务模块)纳入 Sync Rules,时序与监控表排除或做时间窗过滤;
- 前置 3:这些表的主键/唯一标识改造为客户端可生成的 UUID;
- 分阶段:先桌面端(WebView2)验证全链路,再攻 Android WebView 兼容性;
- 冲突策略:字段级 LWW 为主,seq/sortOrder 类服务端仲裁。
3. **不建议**:为离线只读域(新闻/指标/监控)上 PowerSync——用简单缓存即可,同步引擎属于过度设计。
---
## 6. 参考资料
- [PowerSync Service(GitHub,self-hosted 开源)](https://github.com/powersync-ja/powersync-service)
- [PowerSync 源数据库配置文档](https://docs.powersync.com/configuration/source-db/setup)
- [MySQL 后端支持 Beta 公告](https://releases.powersync.com/announcements/mysql-backend-database-support-has-reached-beta)
- [MySQL 后端支持 Alpha 公告](https://releases.powersync.com/announcements/announcing-mysql-as-a-source-database-alpha)
- 本项目:`prisma/schema.prisma`、`server/index.js`、`docs/V0.2/数据库设计文档.md`、`docs/V0.2/任务模块/任务模块数据库设计文档.md`