chore: initial commit of ai site platform

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
whm
2026-07-31 10:19:22 +08:00
commit 6366859bb3
222 changed files with 47313 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
# 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
恢复:有序回放到线上主 → 成功再对齐本地
```
硬约束:主写在线上;断网日志只能回放到线上主;断网窗口非强一致。
---
## 三~十、设计说明(保留)
原 P0P4、响应约定、勿做事项、分阶段 M1M4 已按上文落地M5SQL/导入全收口 + 冲突监控)待续。
与智建平台 dbsync客户端强一致仍以「API 同步写线上」为准,不要只靠触发器异步 outbox 充当主路径。
本意见文档:`E:\project\ai建站\database_fastapi修改意见.md`
实现目录:`yuhengyihao_client\yxd\app_fastapi\`