Skip to content

fix: batch SSE events in use-convert to survive fast reasoning streams - #159

Open
ChHsiching wants to merge 4 commits into
nexu-io:mainfrom
ChHsiching:fix/batch-sse-events
Open

ChHsiching wants to merge 4 commits into
nexu-io:mainfrom
ChHsiching:fix/batch-sse-events

Conversation

@ChHsiching

@ChHsiching ChHsiching commented Sep 27, 2026 •

Copy link
Copy Markdown

Problem

打开思考模式的模型把思考内容按 token 级小帧推送,经 SSE 到达前端实测峰值每秒 240 条 meta 事件,见 #158。use-convert 的接收循环每解析出一个事件就同步写一次 store,PreviewPane 和日志面板跟着整体重渲染一遍。事件来得比渲染快时处理落后于到达,积压的连接缓冲和更新队列把渲染进程内存耗尽,标签页变成「喔唷,崩溃啦!」错误页,错误代码 Out of Memory。issue 里用离线回放验证:每秒 240 条时主线程占用约 100%,每秒 36 条时 92% 但勉强跟上。

Fix

  • use-convert.ts 新增 createEventBatcher:事件先缓冲,每 100 毫秒一次性写进 store,渲染次数从每事件一次降到每窗一次,每秒最多 10 次。
  • 第一个 delta 直通不缓冲,TTFB 不变;done 和 error 直通;回合结束、异常、取消时把缓冲全部写入,不丢事件。
  • store 和组件不动,无新依赖,仍然用 SSE。
  • 断连兜底:流结束但没收到 done 或 error 且不是用户取消时,任务转错误态并写「连接中断,未收到结束事件」日志行。现在的代码这种情况会把任务当成完成。

Verification

  • next/src/lib/__tests__/use-convert.test.ts 新增 13 个用例:7 个纯函数用例,覆盖窗口投递保序、首个 delta 直通、终态直通并先清缓冲、无重复投递、flush 与 dispose;6 个用 fetch 桩驱动 run(),覆盖断连转错误、正常完成、错误终态置任务为 error 且不提交 diff-edit 基线、error 后跟 done 仍按失败收尾、取消不误报;最后一个突发用例在单次网络读取里携带 200 条 meta 帧,断言 200 条全部落地且订阅组件的渲染次数不超过 10 次。新增文件的 13 个用例全部通过。
  • 用 issue 里同方法的每秒 240 条合成事件流回放对比。修复前:高峰期主线程占用约 100%,内存 33→87 MB,结束事件处理不到。修复后:高峰期主线程占用最高 40%,内存峰值 48.5 MB,突发结束后回落到 13.7 MB 谷值,结束事件按时处理。
  • 真机端到端一轮:DeepSeek flash 模型开 low 档思考流,转换官方 article-magazine 示例,36.1 秒收到 4,180 个流块,其中绝大多数是思考内容小帧;任务正常完成,日志 401 条全部落地,页面无崩溃无报错。
live-final
  • pnpm -F @html-anything/next typecheck、test、build 通过;win32 基线无新增失败。

Fixes #158

@nettee nettee left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found one blocking terminal-state issue in the batching change. It is captured inline.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

Comment thread next/src/lib/use-convert.ts Outdated

@nettee nettee left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prior terminal-error issue remains for an error-then-done stream. The inline comment has the concrete failure path and regression coverage needed.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

Comment thread next/src/lib/use-convert.ts

@nettee nettee left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ChHsiching I verified the repair-frontier update for the SSE batching change: an error frame now remains terminal when OpenClaw subsequently emits its unconditional done, preserving the prior diff-edit baseline and surfacing the run as failed. The added regression covers that producer sequence, and the app test suite and TypeScript check pass locally. Thanks for carefully closing the lifecycle gap and adding focused coverage.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk/medium Medium risk change size/L Large change: 300-699 changed lines type/bugfix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

前端每收到一个流式事件就重渲染一次整个界面,思考输出太快时渲染进程内存耗尽

3 participants