Files
Genarrative/docs/technical/RUST_API_SERVER_SSE_INFRASTRUCTURE_DESIGN_2026-04-22.md
kdletters cbc27bad4a
Some checks failed
CI / verify (push) Has been cancelled
init with react+axum+spacetimedb
2026-04-26 18:06:23 +08:00

3.6 KiB
Raw Permalink Blame History

Rust api-server SSE 使用口径2026-04-22

日期:2026-04-22

1. 文档目的

这份文档用于冻结 server-rs/crates/api-server 的 SSE 实现口径。

本轮结论调整为Rust api-server 不再维护自定义 sse.rs 基础设施,统一使用 Axum 内建的 axum::response::sse::{Event, Sse} 能力。

本轮目标只有三个:

  1. 删除 server-rs/crates/api-server/src/sse.rs 自定义模块。
  2. 把现有 custom world message stream 切到 Axum 官方 SSE 类型。
  3. 保持现有业务事件协议与“一次性返回完整事件序列”的兼容语义不变。

本轮不做:

  1. 不改前端消费协议。
  2. 不把 custom world message stream 当场改成真实逐段 token streaming。
  3. 不引入跨 crate 的共享 SSE runtime helper。
  4. 不抽象 reply_delta / session / done / error 等业务事件名。

2. 当前问题

上一轮曾在 server-rs/crates/api-server/src/sse.rs 中抽出自定义 SSE helper用于统一响应头、事件编码、缓冲式输出和实时 writer。

继续保留这套自定义模块的问题是:

  1. Axum 已经提供 Sse<Event>Event::json_data(...) 和标准 SSE body 编码。
  2. 自定义文本编码需要自行维护换行、JSON 序列化、响应头等细节。
  3. 后续真流式接口如果继续沿用自定义 writer会和 Axum 官方生态产生重复抽象。
  4. 当前项目已经以 Axum 作为 Rust HTTP 框架,优先使用框架内建能力更简单。

3. 统一实现口径

Rust api-server 的 SSE 路由统一使用:

use axum::response::sse::{Event, Sse};

有限事件序列使用:

let stream = tokio_stream::iter(events);
Sse::new(stream).into_response()

实时流式接口后续直接使用:

Sse::new(event_stream)

如需保持长连接,可在真实长流接口中追加:

.keep_alive(axum::response::sse::KeepAlive::default())

4. custom world message stream 边界

POST /api/runtime/custom-world/agent/sessions/:sessionId/messages/stream 当前继续保持 Stage 8 文档冻结的最小语义:

  1. 业务层先完成 deterministic 写表。
  2. 读取最新 session snapshot。
  3. 组装 reply_delta
  4. 组装 session
  5. 组装 done
  6. 通过 Axum Sse 返回完整事件序列。

本轮只替换传输层实现,不改变事件顺序、事件名和 payload 结构。

5. 响应头说明

Axum Sse 默认写入:

  1. Content-Type: text/event-stream
  2. Cache-Control: no-cache

当前不再额外写入自定义 X-Accel-Buffering: no helper。

原因:

  1. 本轮目标是移除项目自定义 SSE 模块,避免继续维护传输层封装。
  2. 当前 custom world stream 仍是短生命周期的兼容事件序列,不是长时间 token streaming。
  3. 如果未来某条真实长流接口需要反向代理禁用缓冲,应在该路由或统一 HTTP 中间件层显式评估,而不是恢复自定义 SSE 编码器。

6. 验收标准

当以下条件满足时,本轮视为完成:

  1. api-server/src/sse.rs 已删除。
  2. api-server/src/main.rs 不再声明 mod sse;
  3. custom_world.rs 不再依赖 crate::sse::SseEventBuffer
  4. custom world message stream 使用 Axum Sse<Event> 构造响应。
  5. 为旧自定义 writer 引入的 bytestokio::sync feature 等依赖已清理。
  6. cargo fmt -p api-server 通过。
  7. cargo check -p api-server 通过。
  8. npm run check:encoding 通过。

7. 一句话结论

Rust api-server 的 SSE 能力以 Axum 内建 Sse<Event> 为唯一实现入口,不再保留项目自定义 sse.rs 模块;当前 custom world stream 只替换传输层,不改变业务协议。