4.2 KiB
4.2 KiB
Rust api-server SSE 基础设施设计(2026-04-22)
日期:2026-04-22
1. 文档目的
这份文档用于冻结 server-rs/crates/api-server 内部的 SSE 基础设施抽取口径。
本轮目标只有两个:
- 把当前散落在业务 handler 中的
text/event-stream响应头与事件文本编码逻辑,收口为api-server可复用的 Rust 基础设施。 - 在同一基础设施上补出“实时写事件”的 writer 版本,为后续真流式接口预留稳定入口。
本轮不做:
- 不改前端消费协议
- 不把 custom world message stream 当场改成真实逐段 token streaming
- 不引入跨 crate 的共享
shared-contractsSSE runtime helper - 不同时重构 story / runtime / txt mode 的未来流式接口
2. 当前问题
当前 Rust 侧 SSE 能力只在一个地方手写:
server-rs/crates/api-server/src/custom_world.rs
当前实现存在以下问题:
append_sse_event(...)与build_event_stream_response(...)直接写在业务文件里- SSE 响应头、事件编码规则没有统一入口
- 后续如果再新增第二条 Rust SSE 路由,极容易复制一份近似实现
- 业务层和传输层耦合在一起,不利于测试
3. 抽取边界
本轮只抽以下基础能力:
- 标准 SSE 响应头构造
- 单条事件编码
- 缓冲式 SSE body builder
- 实时写事件的 SSE writer
- 一次性返回完整 SSE 文本的响应构造
- 基于流 body 的实时 SSE 响应构造
本轮明确不抽:
reply_delta / session / done / error这些业务事件名- 事件发送顺序
- custom world session 的查询与回复文本推导
- 业务错误到 SSE
error事件的映射策略
原因固定如下:
- 这些内容属于业务协议,而不是通用传输设施
- 当前不同链路未来很可能有不同事件集合
- 先把传输层抽干净,后续真实流式能力才能稳定复用
4. 基础设施 API 口径
本轮在 server-rs/crates/api-server/src/sse.rs 提供:
SseEventBuffer- 面向当前最小兼容场景
- 内部持有
String - 提供
push_json(event, payload)与into_response()
SseStreamWriter- 面向后续真流式场景
- 内部持有实时写出的 channel sender
- 提供
push_json(event, payload) - writer 被 drop 后,流自动结束
new_sse_stream()- 返回
(SseStreamWriter, Response) - 业务 handler 可先把
Response返回,再异步持续推送事件
- 返回
build_sse_response(body)- 统一写入标准 SSE 响应头
encode_sse_event(body, event, payload)- 只负责把事件编码为:
event: xxx data: {...}
5. 标准响应头
所有通过本基础设施输出的 SSE 响应,统一包含:
Content-Type: text/event-stream; charset=utf-8Cache-Control: no-cacheX-Accel-Buffering: no
当前不默认加入:
Connection: keep-alive
原因:
- 当前 Rust
axum一次性 body 返回场景不依赖显式设置该头 - 保持最小必要头集合,避免提前固化未来长连接策略
6. 与 custom world message stream 的关系
POST /api/runtime/custom-world/agent/sessions/:sessionId/messages/stream 当前仍然保持 Stage 8 文档冻结的最小语义:
- 业务层先完成 deterministic 写表
- 读取最新 session snapshot
- 组装
reply_delta - 组装
session - 组装
done - 一次性返回完整 SSE 文本
本轮变化只在于:
- 事件编码和响应头不再手写在
custom_world.rs - 改由
sse.rs基础设施承接 - 同时补出实时 writer 版本,但当前不强制业务路由马上切换
7. 验收标准
当以下条件满足时,本轮视为完成:
api-server/src/sse.rs已提供可复用 SSE helperapi-server/src/sse.rs已同时提供缓冲式与实时写出式两种能力custom_world.rs不再内联维护 SSE 编码与响应头细节cargo fmt -p api-server通过cargo check -p api-server通过npm run check:encoding通过
8. 一句话结论
本轮把 Rust api-server 里的 SSE 能力收口为“双模式传输层基础设施”,同时提供缓冲式输出与实时写事件 writer,但不改当前业务事件协议,也不强制现有 custom world 路由立即切到真流式。