# database_fastapi 修改意见 > 针对文件:`E:\project\yh_one\new_project\yuhengyihao_client\yxd\app_fastapi\database_fastapi.py` > 背景:需要与线上主库强一致;断网可记日志,恢复后合并回放至线上;主写在线上。 > 对照能力:宇信达智建平台 `dbsync` 出站队列 / 冲突 / 对账(见 `ai建站/docs/数据同步-中间件.md`)。 --- ## 落地状态(已实现) | 项 | 状态 | 位置 | |----|------|------| | 统一写网关 `apply_write` | ✅ | `db_write_gateway.py` | | 写接口收口 | ✅ | insert / update / update/id / delete / sql(DML) | | 库绑定防串库 | ✅ | `sync_binding.py` → `cache/db_bindings/bindings.json` | | 配置 | ✅ | `sync_config.py`(环境变量) | | 断网 pending | ✅ | 复用 `QueueDatabaseManager`,库名默认 `sync_pending` | | 手动回放 | ✅ | `POST /database/sync/replay` | | 绑定/状态 API | ✅ | `/database/sync/*` | | 后台自动回放 | ✅ 可选 | `sync_replay_worker.py`,需 `YXD_SYNC_REPLAY_WORKER=1` | | DDL / 批量 import 收口 | ⏳ 未做 | 仍可直写本地;后续按需收口 | | 冲突队列 API | ⏳ 未做 | 回放失败即停保序,暂无独立 conflicts 列表 | **默认安全**:`YXD_SYNC_MODE` 未配且无 `YXD_ONLINE_API_BASE` 时为 **`local_only`**(只写本地,仍会 ensure 绑定信息)。 配了 `YXD_ONLINE_API_BASE` 且未显式写 `YXD_SYNC_MODE` 时自动升为 **`online_primary`**。 ### 环境变量 | 变量 | 说明 | 默认 | |------|------|------| | `YXD_SYNC_MODE` | `local_only` \| `online_primary` | `local_only`(有 ONLINE_BASE 且未设 mode 则升 primary) | | `YXD_ONLINE_API_BASE` | 线上 API 根,如 `https://api.example.com` | 空 | | `YXD_ONLINE_TIMEOUT_SEC` | 线上写超时 | `8` | | `YXD_OFFLINE_POLICY` | `pending_log` \| `reject` | `pending_log` | | `YXD_SYNC_ENFORCE_BINDING` | 是否强制已绑定 | `true` | | `YXD_SYNC_AUTO_ENSURE_BINDING` | 写时自动 ensure | `true` | | `YXD_SYNC_PENDING_QUEUE` | pending 队列库名 | `sync_pending` | | `YXD_ONLINE_TOKEN_HEADER` | 透传 token 头 | `Authorization` | | `YXD_SYNC_REPLAY_WORKER` | 启后台回放 | 关 | | `YXD_SYNC_REPLAY_INTERVAL_SEC` | 回放间隔秒 | `30` | ### 新增/改动文件 ```text yxd/app_fastapi/ db_write_gateway.py # apply_write / replay_pending sync_config.py sync_binding.py sync_context.py # Request → WriteContext sync_replay_worker.py database_fastapi.py # 写路由改走网关 + /sync/* API ``` ### 同步 API - `GET /database/sync/status` - `POST /database/sync/binding/ensure` - `GET /database/sync/binding` - `GET /database/sync/pending` - `POST /database/sync/replay` body: `{ "limit": 50 }` 请求头需带:`Database-ID`、`User-ID`(或应用已登录)、可选 `Tenant-ID` / `Authorization`。 ### 写路径行为(`online_primary`) ```text 联网:先写线上(Database-ID=online_db_id)→ 成功再写本地镜像 → synced=true 离线 pending_log:不写正式本地业务结果 → 入 sync_pending 队列 → pending=true 离线 reject:直接失败 回放:按 id 升序提交线上 → 成功后写本地并删队列记录;失败即停保序 ``` 绑定键:`(tenant_id, user_id, local_database_id) → online_db_id`(全局唯一)。 --- ## 一、原状结论(改造前) | 项 | 原状 | |----|------| | 写入口 | `/database/permanent/table/data/insert\|update\|update/id\|delete`、`/permanent/sql` 等 | | 落库方式 | 直接 `PermanentDatabaseManager`,**只写本地 SQLite** | | 队列能力 | `queue_database_fastapi.py` 与 permanent **未打通** | | 线上主写 / 断网日志 | **未实现** | --- ## 二、目标模型 ```text 联网:API 写 → 先写线上主库 → 再写本地镜像 断网:API 写 → pending 日志(queue_database)→ 不 formal commit 恢复:有序回放到线上主 → 成功再对齐本地 ``` 硬约束:主写在线上;断网日志只能回放到线上主;断网窗口非强一致。 --- ## 三~十、设计说明(保留) 原 P0–P4、响应约定、勿做事项、分阶段 M1–M4 已按上文落地;M5(SQL/导入全收口 + 冲突监控)待续。 与智建平台 dbsync:客户端强一致仍以「API 同步写线上」为准,不要只靠触发器异步 outbox 充当主路径。 本意见文档:`E:\project\ai建站\database_fastapi修改意见.md`。 实现目录:`yuhengyihao_client\yxd\app_fastapi\`。