85 lines
4.5 KiB
Markdown
85 lines
4.5 KiB
Markdown
---
|
||
name: world_snapshot
|
||
description: 世界状态快照模块(W-04 快照管理)——world_snapshot 表(checksum/version 递增)、快照生成(事务批量+checksum 一致性校验)、查询(分页 {list,total})、恢复(事务回滚无脏数据)、编码字典 snapshot_status/snapshot_type 幂等落库、REST /api/* 统一前缀与错误结构 {code,message,field,detail}。
|
||
---
|
||
|
||
# world_snapshot 模块(W-04 快照管理)
|
||
|
||
## 架构
|
||
|
||
world_snapshot 是域内业务模块:聚合 world/scene/entity 当前状态生成快照,支持查询与恢复。
|
||
通过 `load_world_snapshot()` 挂载到宿主应用(唯一集成点),无独立 app.py/端口。
|
||
|
||
## 数据模型
|
||
|
||
表 `world_snapshot`(models/world_snapshot.json):
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|---|---|---|
|
||
| id | str(32) PK | 主键(getID) |
|
||
| world_id | str(32) | 世界ID(关联 world) |
|
||
| name | str(255) | 快照名称 |
|
||
| snapshot_type | str(32) | full / incremental |
|
||
| snapshot_json | text | 快照内容 JSON(world/scene/entity 聚合) |
|
||
| checksum | str(64) | sha256 校验和 |
|
||
| version | int | 快照版本,按 world 递增(max+1) |
|
||
| status | str(32) | active / restored / expired |
|
||
| snapshot_date | timestamp | 快照日期 |
|
||
| created_at / updated_at | timestamp | 审计时间 |
|
||
|
||
唯一索引 `uk_snap_world_version(world_id, version)` 保证同世界版本不重复。
|
||
|
||
编码字典(init/data.json 幂等落库):
|
||
- `snapshot_status`:active 生效中 / restored 已恢复 / expired 已过期
|
||
- `snapshot_type`:full 全量快照 / incremental 增量快照
|
||
|
||
## 核心逻辑
|
||
|
||
### 快照生成 create_snapshot
|
||
1. 输入白名单校验(world_id 必填且 ≤32、snapshot_type ∈ {full,incremental}、name ≤255)——非法输入 100% 拦截不落库
|
||
2. 同一事务内:`select world ... for update` 行锁该世界 → 批量聚合 scene/entity → 拼 snapshot_json → sha256 checksum
|
||
3. `max(version)+1` 递增(行锁 + 唯一索引双保险)
|
||
4. 事务提交;任何异常整体回滚,返回 `{code,message,field,detail}`
|
||
|
||
### 快照查询 get_snapshot / list_snapshots
|
||
- get:读单条,checksum 重算比对,不匹配返回 `CHECKSUM_MISMATCH`(数据损坏检测)
|
||
- list:分页 `{list,total,page,page_size}`;page/page_size 非整数、status/snapshot_type 不在白名单 → 拦截
|
||
|
||
### 快照恢复 restore_snapshot
|
||
1. 校验快照存在 + checksum 一致性
|
||
2. 同一事务内:先删后插写回 scene/entity(按目标表 information_schema 字段过滤防脏列)→ 更新 world.mode=active → 快照置 restored
|
||
3. 任一步异常 → 事务整体回滚,无脏数据
|
||
|
||
## REST 端点(统一前缀 /api/*)
|
||
|
||
| 端点 | 方法 | 说明 |
|
||
|---|---|---|
|
||
| /world_snapshot/api/snapshot_create.dspy | POST | 生成快照 |
|
||
| /world_snapshot/api/snapshot_get.dspy | GET/POST | 查询单个(含 checksum 校验) |
|
||
| /world_snapshot/api/snapshot_list.dspy | GET/POST | 分页列表 {list,total} |
|
||
| /world_snapshot/api/snapshot_update.dspy | POST | 更新(白名单字段) |
|
||
| /world_snapshot/api/snapshot_delete.dspy | POST | 删除快照记录 |
|
||
| /world_snapshot/api/snapshot_restore.dspy | POST | 恢复快照(事务回滚) |
|
||
| /world_snapshot/api/snapshot_types.dspy | GET | 编码字典:快照类型 [{value,text}] |
|
||
| /world_snapshot/api/snapshot_statuses.dspy | GET | 编码字典:快照状态 [{value,text}] |
|
||
| /world_snapshot/api/snapshot_worlds.dspy | GET | 可选世界列表 [{value,text}] |
|
||
|
||
成功结构:`{"success":true, ...}`
|
||
错误结构:`{"code":"...","message":"...","field":"...","detail":"..."}`
|
||
|
||
## 函数注册(三处同步)
|
||
|
||
`world_snapshot/world_snapshot/init.py` 实现 + `world_snapshot/world_snapshot/__init__.py` import +
|
||
`load_world_snapshot()` 里 `env.xxx = xxx`。新增/删除函数必须三处同步。
|
||
|
||
## 陷阱
|
||
|
||
- **取库名禁止硬编码**:`.py` 用 `ServerEnv().get_module_dbname('world_snapshot')`;.dspy 直接用全局 `get_module_dbname()`
|
||
- **事务 return 位置**:`return` 必须在 `async with` 块外(块内 return 返回 None)
|
||
- **sor.U 仅 2 参数**:主键放 data 里;仅主键时校验非空更新字段
|
||
- **sqlExe 必须带 ns**:无参数查询也传 `{}`
|
||
- **.dspy 禁止 import**:函数经 load_*() 导出;预加载全局 json/debug/getID 等直接可用
|
||
- **dbpools 单例 fork 陷阱**:函数内 `db = DBPools()` 局部创建
|
||
- **sor.C 不自动补 created_at**:插入时显式设置 `created_at`/`updated_at` = curDateString()
|
||
- **LIMIT/OFFSET 用整数**:字符串会渲染成 `LIMIT '5'` 语法错误
|