Skip to content

[bug] 飞书通道 WebSocket 反复崩溃重连,双向收不到消息(事件循环冲突) #2122

Open

Description

@alone-lon

【Bug】飞书通道 WebSocket 反复崩溃重连,双向收不到消息(事件循环冲突)

环境

  • Octop 版本:v1.0.2b8(GitHub 最新 release)
  • 系统:Windows
  • 通道:飞书(FeishuChannel,走 lark_oapi WebSocket 长连接)

现象

  1. 飞书通道"连接测试"通过(凭证/机器人配置正确,open_id 能解析,WS 首次能 connected 到 wss://msg-frontier.feishu.cn)
  2. 但每次连上后几秒内即崩溃,自动重连,循环往复,双向均无法收发消息(机器人发不出消息给用户,用户在飞书发给它也不回)

关键报错(octop.log)

  • RuntimeError: This event loop is already running(FeishuChannel 守护线程内 lark_oapi Client.start() 调 loop.run_until_complete 时)
  • RuntimeError: Task ... got Future ... attached to a different loop(_receive_message_loop / _ping_loop 的 create_task 挂错 loop)
  • 后续:ping failed, err: Event loop is closed / receive message loop exit / Feishu WebSocket thread orphaned / 反复 reconnecting

代码定位

  • Octop 侧:octop_gateway/channels/feishu.py 的 _run_ws_thread()(约 268-292 行)
    在守护线程内 new_event_loop + set_event_loop,并尝试 ws_client_module.loop = loop 改写 lark_oapi.ws.client 的模块级 loop,再调 self._ws_client.start()
  • 飞书 SDK 侧:lark_oapi/ws/client.py 顶层
    try: loop = asyncio.get_event_loop()
    except RuntimeError: loop = asyncio.new_event_loop(); asyncio.set_event_loop(loop)
    Client.start() 内部所有 run_until_complete / create_task 均引用该模块级全局 loop;若 lark_oapi.ws.client 曾在主线程(Octop 主框架本身是 async 环境)被 import 过,该全局 loop 很可能就是主线程正在运行的 loop,子线程再 run_until_complete 即冲突

预期
FeishuChannel 能稳定保持 WebSocket 长连接,双向正常收发消息

请修复
核心矛盾:lark_oapi SDK 假设"单线程单 loop",Octop 把它放进守护线程并与主 async 框架共存。建议方向(供参考,最终方案你们定):

  • 让 lark_oapi.ws.client 的 Client 支持注入独立 event loop / 或在 start() 内基于线程本地(threading.local)持有 loop,而非模块级全局变量
  • 或 Octop 侧不再"改写模块全局 loop",改为确保子线程内 import/构造 Client 时其模块级 loop 就是该线程新建的 loop(比如子线程内重新 import lark_oapi.ws.client,避免复用主线程已初始化的模块状态)
  • 修复后请补充"主 async 框架 + 守护线程跑 WS 客户端"场景的回归测试,防止再次回归

附:完整日志片段
2026-10-16 20:03:31,669 INFO octop_gateway.channels.feishu — Feishu WebSocket client connecting (daemon thread, session=76dd1721-...)
2026-10-16 20:03:32,073 INFO Lark — connected to wss://msg-frontier.feishu.cn/ws/v2?...
2026-10-16 20:03:32,073 ERROR octop_gateway.channels.feishu — Feishu WebSocket thread failed
Traceback (most recent call last):
...
loop.run_until_complete(_select())
...
RuntimeError: This event loop is already running
2026-10-16 20:03:32,134 WARNING Lark — ping failed, err: Event loop is closed
2026-10-16 20:03:32,134 ERROR Lark — receive message loop exit, err: Task <...> got Future attached to a different loop
2026-10-16 20:03:42,006 ERROR octop_gateway.channels.feishu — Feishu WebSocket thread orphaned; connection slot may remain until it exits
(后续 20:12 起反复 reconnect → connected → exit,死循环)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions