重写
This commit is contained in:
140
docs/technical/ASSET_ENTITY_BINDING_REDUCER_DESIGN_2026-04-21.md
Normal file
140
docs/technical/ASSET_ENTITY_BINDING_REDUCER_DESIGN_2026-04-21.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# 资产对象业务实体绑定 reducer 设计
|
||||
|
||||
日期:`2026-04-21`
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
这份文档用于冻结 `M6` 中“对象绑定业务实体 reducer”的首版落地方案。
|
||||
|
||||
当前已经完成:
|
||||
|
||||
1. 浏览器可通过 `PostObject` 把文件直传到私有 OSS。
|
||||
2. `POST /api/assets/objects/confirm` 已能确认对象存在。
|
||||
3. `asset_object` 已按 `bucket + object_key` 写入 SpacetimeDB。
|
||||
|
||||
下一步要补上的最小闭环是:
|
||||
|
||||
1. 已确认的 `asset_object` 能绑定到某个业务实体。
|
||||
2. 绑定关系由 SpacetimeDB 持久化。
|
||||
3. Axum 提供最小 HTTP facade,避免前端直接拼 SpacetimeDB reducer 参数。
|
||||
|
||||
## 2. 当前阶段不直接创建强业务表的原因
|
||||
|
||||
当前先落通用 `asset_entity_binding`,不直接创建 `character_visual_asset / scene_image_asset / sprite_sheet_asset`。
|
||||
|
||||
原因固定如下:
|
||||
|
||||
1. 角色、场景、精灵等强业务表的完整字段还没有冻结。
|
||||
2. 当前最紧急的工程闭环是“确认后的对象能被实体引用”,不是完整发布模型。
|
||||
3. 通用绑定表可以先承接旧接口迁移中的 `entityId + slot` 关系,后续再由强业务表逐步替换或派生。
|
||||
|
||||
## 3. 表设计
|
||||
|
||||
首版新增 private table:
|
||||
|
||||
1. `asset_entity_binding`
|
||||
|
||||
字段如下:
|
||||
|
||||
| 字段名 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `binding_id` | `String` | 是 | 主键,固定 `assetbind_` 前缀。 |
|
||||
| `asset_object_id` | `String` | 是 | 被绑定的 `asset_object.asset_object_id`。 |
|
||||
| `entity_kind` | `String` | 是 | 业务实体类型,例如 `character`、`scene`、`profile`。 |
|
||||
| `entity_id` | `String` | 是 | 业务实体 ID。 |
|
||||
| `slot` | `String` | 是 | 实体上的资产槽位,例如 `primary_visual`、`cover`、`sprite_sheet`。 |
|
||||
| `asset_kind` | `String` | 是 | 资产类型,例如 `character_visual`。 |
|
||||
| `owner_user_id` | `Option<String>` | 否 | 归属用户,当前仅作为服务端传入的记录字段。 |
|
||||
| `profile_id` | `Option<String>` | 否 | 归属 profile。 |
|
||||
| `created_at` | `Timestamp` | 是 | 首次绑定时间。 |
|
||||
| `updated_at` | `Timestamp` | 是 | 最近绑定更新时间。 |
|
||||
|
||||
索引如下:
|
||||
|
||||
1. `entity_kind + entity_id + slot`
|
||||
用于按实体槽位查当前绑定。
|
||||
2. `asset_object_id`
|
||||
用于按对象反查被哪些业务实体引用。
|
||||
|
||||
## 4. 幂等规则
|
||||
|
||||
绑定写入按以下规则执行:
|
||||
|
||||
1. `asset_object_id` 必须已存在于 `asset_object`。
|
||||
2. `entity_kind + entity_id + slot` 作为首版幂等定位键。
|
||||
3. 同一实体槽位重复绑定时,不新增第二行。
|
||||
4. 重复绑定会复用原 `binding_id` 与 `created_at`,更新 `asset_object_id / asset_kind / owner_user_id / profile_id / updated_at`。
|
||||
5. 不同槽位可以绑定同一个 `asset_object_id`。
|
||||
|
||||
## 5. reducer / procedure 设计
|
||||
|
||||
SpacetimeDB 新增:
|
||||
|
||||
1. `bind_asset_object_to_entity`
|
||||
reducer,只返回 `Result<(), String>`,供后续模块内部复用。
|
||||
2. `bind_asset_object_to_entity_and_return`
|
||||
procedure,面向 Axum 同步接口返回最终绑定快照。
|
||||
|
||||
procedure 返回结构采用:
|
||||
|
||||
1. `ok`
|
||||
2. `record`
|
||||
3. `error_message`
|
||||
|
||||
与 `asset_object` 确认 procedure 保持一致,便于 `spacetime-client` 做统一错误映射。
|
||||
|
||||
## 6. Axum HTTP facade
|
||||
|
||||
首版新增接口:
|
||||
|
||||
`POST /api/assets/objects/bind`
|
||||
|
||||
请求体:
|
||||
|
||||
| 字段名 | 类型 | 必填 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| `assetObjectId` | `String` | 是 | 已确认对象 ID。 |
|
||||
| `entityKind` | `String` | 是 | 业务实体类型。 |
|
||||
| `entityId` | `String` | 是 | 业务实体 ID。 |
|
||||
| `slot` | `String` | 是 | 资产槽位。 |
|
||||
| `assetKind` | `String` | 是 | 资产类型。 |
|
||||
| `ownerUserId` | `String` | 否 | 当前阶段由后端调用方显式传入。 |
|
||||
| `profileId` | `String` | 否 | 当前阶段由后端调用方显式传入。 |
|
||||
|
||||
响应体核心字段:
|
||||
|
||||
1. `bindingId`
|
||||
2. `assetObjectId`
|
||||
3. `entityKind`
|
||||
4. `entityId`
|
||||
5. `slot`
|
||||
6. `assetKind`
|
||||
7. `ownerUserId`
|
||||
8. `profileId`
|
||||
9. `createdAt`
|
||||
10. `updatedAt`
|
||||
|
||||
## 7. 当前阶段安全边界
|
||||
|
||||
当前接口是 Axum facade,不是前端直接调用 SpacetimeDB reducer 的最终权限模型。
|
||||
|
||||
约束如下:
|
||||
|
||||
1. 当前不把长期 OSS AK/SK 下发给客户端。
|
||||
2. 当前不让客户端直接写 private table。
|
||||
3. `owner_user_id` 当前只作为记录字段,不作为可信授权依据。
|
||||
4. 后续接入 SpacetimeDB 身份透传后,绑定 reducer 的授权必须改为基于可信身份,不信任客户端传入的用户 ID。
|
||||
|
||||
## 8. 完成定义
|
||||
|
||||
首版完成条件:
|
||||
|
||||
1. `module-assets` 提供绑定输入、快照、结果结构与字段校验。
|
||||
2. `spacetime-module` 新增 `asset_entity_binding` 表与绑定 reducer/procedure。
|
||||
3. `spacetime-client` 生成最新 Rust bindings 并封装绑定 procedure。
|
||||
4. `api-server` 暴露 `POST /api/assets/objects/bind`。
|
||||
5. 本地测试覆盖字段错误与 “asset_object 不存在不能绑定”。
|
||||
|
||||
## 9. 一句话结论
|
||||
|
||||
当前阶段先用通用 `asset_entity_binding` 把已确认 OSS 对象绑定到业务实体槽位,强业务资产表等字段稳定后再继续拆分。
|
||||
Reference in New Issue
Block a user