抽离runtime story可替换传输层

This commit is contained in:
2026-04-20 09:53:05 +00:00
parent 06a8853167
commit e8beb0a988
4 changed files with 370 additions and 71 deletions

View File

@@ -11,6 +11,7 @@
- [SPACETIME_AUTH_TOKEN_FALLBACK_HOTFIX_2026-04-20.md](./SPACETIME_AUTH_TOKEN_FALLBACK_HOTFIX_2026-04-20.md):本地 token 失效时自动降级匿名连接,并提示“登录已过期”的热修记录。
- [STDB_AUTH_TAIL_PHASE1_AUTO_GUEST_CREDENTIAL_REMOVAL_2026-04-20.md](./STDB_AUTH_TAIL_PHASE1_AUTO_GUEST_CREDENTIAL_REMOVAL_2026-04-20.md)Auth 尾巴清理第一段,删除前端自动游客用户名/密码残留。
- [STDB_AUTH_TAIL_PHASE2_TOKEN_SLOT_SPLIT_2026-04-20.md](./STDB_AUTH_TAIL_PHASE2_TOKEN_SLOT_SPLIT_2026-04-20.md):将 STDB token 与旧 HTTP Bearer token 拆成独立存储槽。
- [RUNTIME_STORY_TO_STDB_PHASE1_TRANSPORT_ABSTRACTION_2026-04-20.md](./RUNTIME_STORY_TO_STDB_PHASE1_TRANSPORT_ABSTRACTION_2026-04-20.md):把 `runtimeStoryService` 改成可替换 transport为后续 STDB provider 接入预留稳定边界。
- [TASK_AUTO_COMMIT_WORKFLOW_2026-04-20.md](./TASK_AUTO_COMMIT_WORKFLOW_2026-04-20.md):任务完成后按文件边界自动提交的脚本与协作约定。
- [NODE_DEV_STARTUP_HOTFIX_2026-04-20.md](./NODE_DEV_STARTUP_HOTFIX_2026-04-20.md)`npm run dev` 启动失败的热修记录、根因与验证结果。
- [NODE_SERVER_KNOWLEDGE_GRAPH_2026-04-08.md](./NODE_SERVER_KNOWLEDGE_GRAPH_2026-04-08.md):当前 Node 运行时后端的技术栈、入口、鉴权、存储与接口知识图谱。

View File

@@ -0,0 +1,105 @@
# Runtime Story 迁移到 STDB Phase 1传输层抽离2026-04-20
更新时间:`2026-04-20`
## 1. 本轮目标
本轮只处理 `runtime story` 迁移的第一阶段基线问题:
1.`src/services/runtimeStoryService.ts` 从“直接硬编码 HTTP 请求”改成“可替换 transport”
2. 保持上层 `hook / coordinator / 页面` 的调用方式不变
3. 给后续接入 SpacetimeDB provider 预留稳定插槽
本轮**不处理**以下事项:
1. 不把 `/api/runtime/story/*` 直接替换成 STDB
2. 不迁移 `server-node/src/modules/story/*` 里的 runtime 结算逻辑
3. 不改动 `runtimeStoryCoordinator`、页面层和选项分发层的上层契约
4. 不改动任何剧情、文案、函数能力面和业务规则
## 2. 为什么先抽 transport
`runtime story` 当前不是一个单薄的读写接口,而是一整条运行时状态机链路:
1. 读取状态:`GET /api/runtime/story/state/:sessionId`
2. 结算动作:`POST /api/runtime/story/actions/resolve`
3. 上层 `runtimeStoryCoordinator` 依赖其统一返回快照、presentation、viewModel
如果直接在这一轮把上层调用点改成 STDB会产生两个问题
1. 需要同时修改服务层、hook 层、状态持久化和测试,范围过大
2. 很容易把“迁移后端传输”误做成“重写 runtime story 业务流程”
因此本轮先把问题缩成一条更稳的工程边界:
1. `runtimeStoryService` 负责对外暴露稳定 API
2. `transport` 负责具体从 HTTP 或未来 STDB 获取响应
3. 响应统一在服务层做快照 rehydrate避免各 transport 各自复制一份归一化逻辑
## 3. 本轮代码改动
### 3.1 `runtimeStoryService.ts`
新增以下类型与入口:
1. `RuntimeStoryActionRequest`
2. `RuntimeStoryTransport`
3. `setRuntimeStoryTransport(...)`
4. `resetRuntimeStoryTransport()`
默认实现策略:
1. 把原来的 HTTP GET/POST 逻辑收进内部默认 transport
2. 模块级 `runtimeStoryTransport` 默认指向 HTTP transport
3. 公开函数 `getRuntimeStoryState(...)` / `resolveRuntimeStoryAction(...)` 不改签名
4. 公开函数统一对 transport 返回值执行 `rehydrateSavedSnapshot(...)`
这样后续接入 STDB 时只需要:
1. 提供一个新的 `RuntimeStoryTransport`
2. 在合适的初始化位置注入 `setRuntimeStoryTransport(...)`
3. 无需继续修改调用 `runtimeStoryService` 的上层代码
### 3.2 `runtimeStoryService.test.ts`
本轮新增两类防回退测试:
1. 可以替换 transport且调用方仍沿用既有公开 API
2. 调用 `resetRuntimeStoryTransport()` 后,会回到默认 HTTP 路径
同时保留原有断言:
1. HTTP 请求路径和 body 结构不变
2. runtime payload 合并规则不变
3. option interaction / disabled 状态 / snapshot story 优先级不变
## 4. 当前迁移边界
完成本轮后,`runtime story` 的迁移边界变为:
1. 上层依赖的是 `runtimeStoryService`,而不是 HTTP 地址
2. 传输层已经可替换,但默认实现仍是 Express HTTP
3. STDB provider 可以在后续阶段单独接入,不再需要先动 hook 和页面
也就是说,这一轮交付的是“迁移支点”,不是“业务已经迁移完成”。
## 5. 后续阶段建议
建议继续按以下顺序推进:
1. Phase 2设计并实现 `runtime story` 的 STDB transport/provider
2. Phase 3把现有 runtime story 读写 contract 映射到 STDB 表 / reducer / subscription
3. Phase 4验证 Express `/api/runtime/story/*` 是否还能保留为兼容壳层,或者彻底下线
这样可以持续保持每一阶段都具备:
1. 清晰边界
2. 最小改动面
3. 可测试回退点
## 6. 本轮涉及文件
1. `src/services/runtimeStoryService.ts`
2. `src/services/runtimeStoryService.test.ts`
3. `docs/technical/RUNTIME_STORY_TO_STDB_PHASE1_TRANSPORT_ABSTRACTION_2026-04-20.md`
4. `docs/technical/README.md`