fix: send SSE heartbeat to prevent WebChat disconnect during compression#7003
fix: send SSE heartbeat to prevent WebChat disconnect during compression#7003he-yufeng wants to merge 1 commit intoAstrBotDevs:masterfrom
Conversation
When context compression triggers with slow reasoning models (e.g. deepseek-reasoner), the backend can go 30+ seconds without pushing any SSE data. The client-side EventSource / browser then assumes the connection is dead and disconnects, causing the WebUI to hang indefinitely since it never receives the eventual response. Fix: yield an SSE comment (`: heartbeat`) on every empty poll cycle. Comment lines are defined in the SSE spec as keep-alive signals -- the EventSource API ignores them but the HTTP connection stays open. Fixes AstrBotDevs#6938
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! 此拉取请求旨在解决 WebChat 客户端在后端执行长时间操作(如上下文压缩)时,因 SSE 连接超时而断开的问题。通过在无数据传输期间发送 SSE 心跳信号,确保客户端连接持续活跃,从而避免 WebUI 假死并提升用户在与推理模型交互时的体验稳定性。 Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request implements a Server-Sent Events (SSE) heartbeat mechanism to prevent client timeouts during potentially long-running backend operations, such as context compression. This is achieved by returning a sentinel value when asyncio.wait_for times out in _poll_webchat_stream_result and subsequently sending an SSE heartbeat comment (: heartbeat\n\n) in the stream function when this sentinel is detected. The review suggests improving readability and maintainability by extracting the ": heartbeat\n\n" string into a module-level constant.
| # doesn't time out during slow backend ops like | ||
| # context compression with reasoning models (#6938). | ||
| if not client_disconnected: | ||
| yield ": heartbeat\n\n" |
问题
使用推理模型(如 deepseek-reasoner)时,如果对话历史较长触发了上下文压缩,压缩过程可能需要 30+ 秒。在这段时间内 SSE stream 没有推送任何数据,客户端 EventSource 判定连接超时并主动断开,导致 WebUI 假死(一直转圈)。
后端最终完成压缩并生成回复后,由于前端已断开连接,消息无法推送,用户只能刷新页面。
修复
在
_poll_webchat_stream_result返回空结果(queue 无新数据)时,yield 一个 SSE comment(: heartbeat\n\n)。根据 SSE 规范,以
:开头的行是 comment/keep-alive 信号——客户端 EventSource API 会忽略 comment 内容,但 HTTP 连接保持活跃。这样即使压缩耗时很长,连接也不会断开。改动只有 1 个文件 8 行,零副作用。
Fixes #6938
Summary by Sourcery
Bug Fixes: