Skip to content

fix: send SSE heartbeat to prevent WebChat disconnect during compression#7003

Open
he-yufeng wants to merge 1 commit intoAstrBotDevs:masterfrom
he-yufeng:fix/webchat-timeout
Open

fix: send SSE heartbeat to prevent WebChat disconnect during compression#7003
he-yufeng wants to merge 1 commit intoAstrBotDevs:masterfrom
he-yufeng:fix/webchat-timeout

Conversation

@he-yufeng
Copy link
Copy Markdown
Contributor

@he-yufeng he-yufeng commented Mar 26, 2026

问题

使用推理模型(如 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:

  • Prevent WebChat SSE connections from timing out while waiting for slow context compression or reasoning model responses.

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
@dosubot dosubot bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Mar 26, 2026
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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

  • 引入 SSE 心跳机制: 在 WebChat 后端长时间无数据传输时(例如进行上下文压缩),通过发送 SSE 注释(: heartbeat\n\n)作为心跳信号,防止客户端 EventSource 因超时而断开连接。
  • 解决 WebUI 假死问题: 修复了在使用推理模型进行耗时较长的上下文压缩时,WebUI 出现假死(一直转圈)并需要用户手动刷新才能恢复的问题,提升了用户体验。
  • 优化连接稳定性: 确保即使后端操作耗时较长,客户端与服务器之间的 HTTP 连接也能保持活跃,避免因连接中断导致消息无法推送。
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@dosubot dosubot bot added the feature:chatui The bug / feature is about astrbot's chatui, webchat label Mar 26, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

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"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

为了提高代码的可读性和可维护性,建议将 SSE 心跳消息 ": heartbeat\n\n" 提取为一个模块级别的常量。这样可以避免在代码中出现魔法字符串,并且如果将来需要修改心跳消息,只需在一个地方进行更改。

例如,可以在文件顶部定义:

SSE_HEARTBEAT = ": heartbeat\n\n"

然后在 stream 函数中使用它。

Suggested change
yield ": heartbeat\n\n"
yield SSE_HEARTBEAT

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

Labels

feature:chatui The bug / feature is about astrbot's chatui, webchat size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]WebChat 长连接在上下文压缩时因超时断开,导致 WebUI 假死 (使用推理模型时尤其严重)

1 participant