Enable Binding-scoped agent push/pull, empty-table schema ensure, SyncPage inspect/drop-table, default module import, and agent-bound publish docs from the 宇恒联调意见. Co-authored-by: Cursor <cursoragent@cursor.com>
150 lines
6.7 KiB
Markdown
150 lines
6.7 KiB
Markdown
# 智建修改意见(松离线 + UUID 主键一致性)
|
||
|
||
> 配套文档:同目录 `database_fastapi修改意见.md`(宇恒客户端写网关 / 双轨写)
|
||
> 目标:离线写入不破坏联网后的**数据一致 + 主键一致**;对账可兜底。
|
||
> 对照能力:本仓库 `docs/数据同步-中间件.md`(dbsync outbox / ingest / reconcile / 冲突队列)。
|
||
|
||
---
|
||
|
||
## 一、结论摘要
|
||
|
||
| 项 | 结论 |
|
||
|----|------|
|
||
| 对账引擎 | **不必从零重做**;dbsync 已有按主键 upsert、ingest、reconcile、冲突队列 |
|
||
| 真正要改 | **表主键约定(UUID)** + **写入口语义(认客户端 id / upsert)** + **与宇恒绑定对齐** |
|
||
| 推荐模型 | **松 + UUID**:离线本地先按最终主键落库;联网同主键幂等 upsert 到线上 |
|
||
| 禁止 | 同步键依赖两端各自 `INTEGER AUTOINCREMENT` |
|
||
|
||
宇恒侧(客户端)负责:补 UUID、松离线本地落库 + pending、回放幂等。
|
||
智建侧负责:线上按 UUID upsert、通道/对账/冲突、表结构与发号规则。
|
||
|
||
---
|
||
|
||
## 二、与宇恒文档的分工
|
||
|
||
| 端 | 文档 | 职责 |
|
||
|----|------|------|
|
||
| 宇恒客户端 | `database_fastapi修改意见.md` | `apply_write`、pending、binding、`online_primary` |
|
||
| 智建平台 | **本文** | 线上主库语义、dbsync、表约定、对账 API 对业务可用 |
|
||
|
||
接法二选一(长期建议 ①):
|
||
|
||
| 接法 | 含义 | 智建改动量 |
|
||
|------|------|------------|
|
||
| **① 走 dbsync** | 宇恒本地 = B;松离线写 B(带 UUID);通道 B↔A | 表结构 + 配置为主,代码改少 |
|
||
| **② HTTP 双写** | 宇恒直打 `/database/permanent/...` | 线上 insert **必须**变 upsert,且强制客户端 `id` |
|
||
|
||
---
|
||
|
||
## 三、表结构约定(A / B 两端)
|
||
|
||
1. 参与同步的业务表主键为 **`id TEXT`(UUID 字符串)**,不用自增整数当同步键。
|
||
2. 建议列:`updated_at` / `version`(与 dbsync 版本跳过、冲突策略对齐)。
|
||
3. 通道 `pk_columns`:非默认 `id` 时显式配置。
|
||
4. 存量自增表:迁移生成 UUID,或暂不纳入同步白名单,仅新表用 UUID。
|
||
5. dbsync 触发器已 `CAST(pk AS TEXT)`,字符串 UUID **原生兼容**;改的是建表习惯,不是中间件内核。
|
||
|
||
---
|
||
|
||
## 四、接法 ①:走 dbsync(推荐)
|
||
|
||
### 已有、可直接用
|
||
|
||
- 本地变更 → `_ajz_sync_outbox` → worker 推线上
|
||
- `POST .../ingest`:按主键 upsert(示例已是 `"id": "c-001"`)
|
||
- `POST .../reconcile`:主键集合补缺
|
||
- 冲突队列 + LWW / queue 策略
|
||
- 双向通道约每分钟自动对账
|
||
|
||
### 建议补强
|
||
|
||
| 优先级 | 项 | 说明 |
|
||
|--------|----|------|
|
||
| P0 | 文档/控制台规范 | 写死:同步表白名单必须 UUID 主键;松离线以客户端已带 `id` 为准 |
|
||
| P0 | 写入口拒无 id | ingest / 业务写:无 `id` → 400,或服务端生成 UUID **并回写响应**(松离线仍优先客户端生成) |
|
||
| P1 | 库绑定对齐 | 宇恒 `online_db_id` 与智建租户库 / 通道 remote 可查询、可登记;避免仅本地 hash 对不上真实库 |
|
||
| P1 | 业务可调对账 | 现 sync API 偏管理员;提供租户内用户/agent 代理调用 ingest/reconcile,或网关代调 |
|
||
| P2 | 同 PK 内容对账 | 当前 reconcile 偏主键集合;可选 version/hash 不一致 → 冲突队列 |
|
||
|
||
### 松离线数据流(①)
|
||
|
||
```text
|
||
离线:宇恒本地 B 按最终 UUID 落库(可标未同步)+ 可选 pending
|
||
联网:触发器/回放 → 同 PK upsert → A
|
||
兜底:reconcile 补主键集合差;冲突进 conflicts
|
||
```
|
||
|
||
---
|
||
|
||
## 五、接法 ②:HTTP 双写(短期兼容宇恒网关)
|
||
|
||
宇恒当前:`online_primary` 下同 body 先写线上再写本地,**不会**把线上自增 `inserted_id` 回填本地。
|
||
|
||
智建线上 permanent 写接口必须:
|
||
|
||
1. **`insert` = upsert by `id`**(有则更新,无则插入);请求**必须带 `id`**。
|
||
2. 响应带回 **`id` + `version`(可选)**,便于客户端校验。
|
||
3. `update` / `delete` 统一按同一 `id`;禁止「无 id 靠自增」。
|
||
4. 建表默认主键模板改为 UUID,不再默认 `INTEGER AUTOINCREMENT`。
|
||
5. (可选)按 `online_db_id` + 表暴露 reconcile,或复用 dbsync reconcile。
|
||
|
||
未改以上语义时,即使客户端用 UUID,线上若仍自增,双轨主键仍会漂。
|
||
|
||
---
|
||
|
||
## 六、落地顺序(智建)
|
||
|
||
1. **规范 + 迁移**:同步表白名单,主键 UUID。
|
||
2. **选定接法**:优先 ①;若短期 ②,先改 permanent 写为 upsert。
|
||
3. **写入口强制带 `id`**(缺则 400 或服务端生成并返回)。
|
||
4. **绑定**:租户/用户 ↔ 线上库 ID 可查,与宇恒 `cache/db_bindings` 对齐。
|
||
5. **对账**:业务可读 API 或网关代调;冲突走现有 conflicts。
|
||
6. **文档**:离线写入 = 最终主键;联网只做同 PK 幂等,不重新发号。
|
||
|
||
---
|
||
|
||
## 七、验收标准
|
||
|
||
- 离线插入一行(客户端 UUID)→ 联网后线上与本地 **同一 `id`**,无重复行。
|
||
- 同一 UUID 重复提交 / 回放 → **幂等**,不多行。
|
||
- 断网窗口结束回放后,主键集合对账无持续缺口(或缺口可一键 reconcile 清掉)。
|
||
- 并发改同 PK → 进冲突队列或按约定 LWW,不静默改主键。
|
||
- 未纳入白名单的自增旧表:不同步或明确排除,避免误配通道。
|
||
|
||
---
|
||
|
||
## 八、勿做事项
|
||
|
||
- 不要用「两端自增 + 事后对账」充当主路径。
|
||
- 不要只靠触发器异步 outbox 充当客户端主写路径却仍让 HTTP insert 自增发号(两套语义打架)。
|
||
- 不要在回放失败时换新主键重试。
|
||
- 不要让管理员专用 sync API 成为唯一对账入口却要求终端用户自愈(需代理或网关)。
|
||
|
||
---
|
||
|
||
## 九、相关路径
|
||
|
||
| 项 | 路径 |
|
||
|----|------|
|
||
| 本文 | `E:\project\ai建站\智建修改意见.md` |
|
||
| 宇恒写网关意见 | `E:\project\ai建站\database_fastapi修改意见.md` |
|
||
| dbsync 说明 | `E:\project\ai建站\docs\数据同步-中间件.md` |
|
||
| dbsync 实现 | `platform/internal/dbsync/` |
|
||
| 宇恒网关实现 | `yuhengyihao_client/yxd/app_fastapi/db_write_gateway.py` 等 |
|
||
|
||
---
|
||
|
||
## 十一、模块导入默认能力(方案 A)
|
||
|
||
> **正式条目已写入联调意见,请以此为准:**
|
||
> `E:\project\ai建站\联调后修改意见-宇恒松离线.md` → **§5.6 Z9(方案 A)**
|
||
> (§0 结论表已挂「Z9 模块导入默认能力」)
|
||
|
||
摘要:生成/发布时业务 resource **默认**带 `import`(及 `export`),列表 `actions` 对齐;publish/merge 可兜底。绑定权限解决「谁能调」,方案 A 解决「表是否允许导入」。
|
||
|
||
---
|
||
|
||
## 十二、一句话(同步 + 导入)
|
||
|
||
松离线要对齐的是 **UUID 主键 + upsert**;模块灌数要对齐的是 **绑定权限 + 蓝图默认开放 import(方案 A / Z9)**——细则见联调意见 §5.6。
|