Skip to content

[BUG] WebSocket 重连后 orphanBinaryPayloads / pendingReplayStreamIds 未清空,导致跨连接数据污染 #18

Description

@pallyoung

问题描述

packages/web/src/ws/client.tshandleClose() 在 WebSocket 重连时,不清空以下 Map:

  • orphanBinaryPayloads(line 93)
  • pendingReplayStreamIds(line 88)

服务端每次新建 WsClient 实例时,nextStreamId 从 1 重新计数。重连后新连接的 streamId=1 帧会命中旧连接遗留在 Map 中的 entry,导致 replay 数据路由到错误的处理器,出现终端输出乱码或 replay promise 永远不 resolve。

复现场景

  1. 用户打开终端,触发 replay 请求(streamId=1)
  2. 网络闪断,replay binary 帧尚未到达,对应 streamId 在 pendingReplayStreamIds 中留存
  3. WebSocket 自动重连,服务端重新从 streamId=1 开始
  4. 新连接的第一个 replay binary 帧(streamId=1)命中旧的 pending entry,数据污染

相关代码

} catch (err) {
console.error(`Error in event listener for ${topic}:`, err);
}
}
}
}
private isTerminalBinaryEventData(data: unknown): data is TerminalBinaryEventData {
return (
typeof data === 'object' &&
data !== null &&
'transport' in data &&
'streamId' in data &&
'size' in data &&
(data as { transport?: unknown }).transport === 'binary'
);

修复建议

handleClose() 中清空这两个 Map,并 reject 所有 pending 的 replay promise,避免旧状态污染新连接。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions