跳转到内容

实时事件

RTC Agent 通过 Centrifuge WebSocket 推送实时事件,采用 双频道架构:Topic 频道保证可靠性,Live 频道提供低延迟。前端收到事件后更新本地状态,实现前后端的实时同步。

频道标识存储用途特点
Topictopic:u=<userID>持久化状态变更事件可靠、有序、支持离线恢复
Livelive:u=<userID>非持久化流式消息中间 chunks低延迟、即发即弃

💡 为什么需要两个频道? 状态变更(如消息创建、Turn 完成)不能丢失——需要持久化和顺序保证。但流式输出的中间 chunk 只需要”尽快到达”——丢了也不要紧,因为最终会收到完整消息。分开处理,各取所长。


事件类型Topic 频道Live 频道说明
session.created会话创建
session.updated会话更新(标题、状态等)
turn.createdTurn 创建
turn.updatedTurn 状态变更
message.created消息创建
message.updated(流完成)流式消息的最终完整版本
message.updated(流中间 chunk)打字机效果的实时片段
rtc.created预留(当前未发出)
rtc.updatedRTC 状态变更

每个事件都是一个 Update——描述实体(Session / Turn / Message / RTC)的变化:

{
"id": "update-uuid",
"items": [
{ "entity": "message", "action": "created", "entity_id": "msg-uuid" }
],
"data_list": [{ "id": "msg-uuid", "role": "assistant", "..." : "..." }],
"offset": 42
}
字段类型说明
idUUIDUpdate 唯一标识
itemsarray变化条目列表
items[].entitystring实体类型:session / turn / message / rtcfile 为预留,当前未使用)
items[].actionstring操作类型:created / updateddeleted 为预留,当前未使用;删除通过 data_list 中的 deleted_at 表达)
items[].entity_idUUID实体 ID
data_listarray实体完整数据(可选,与 items 一一对应)
offsetinteger用户维度单调递增偏移量

Offset 是事件可靠性的核心保障——每个 Topic 事件分配严格递增的 Offset,客户端通过检测 Offset 连续性发现丢失的事件。

特性说明
单调递增同一用户的 Topic 事件 Offset 严格递增
连续性检测客户端发现 Offset 跳跃时自动补全
持久化Offset 存储在 IndexedDB,页面刷新后恢复
Epoch 机制历史数据被清理时 Epoch 变更,客户端从最新位置开始
Gap 占位离线恢复时,服务端发送 {"type": "gap", "data": {}} 事件填充 Offset 空洞,客户端收到后只推进 Offset,不做业务处理

💡 类比:Offset 就像邮件的编号。如果你收到了第 1、2、4 封信,你会意识到第 3 封丢了——然后去邮局补领。


AI 回复采用流式输出,中间 chunks 通过 Live 频道实时推送,最终完整消息通过 Topic 频道保证可靠性。

阶段频道行为
首 chunkTopic创建消息记录,推送 message.created,同时写入 Redis 缓冲
中间 chunksLive追加到 Redis 缓冲,推送到 Live 频道实时显示
流结束Topic从 Redis 读取所有 chunks 拼接完整内容,更新数据库,推送 message.updated

客户端断网重连后,系统自动检测 Offset 并补全缺失的事件。

场景行为用户感知
短暂断网自动推送离线期间的消息无缝,消息自动出现
长时间断网检测 Offset 跳跃,拉取历史短暂加载后消息补齐
历史被清理Epoch 变更,从最新位置开始历史消息不再显示
组件职责
Centrifuge SDK自动重连、Token 刷新
IndexedDB持久化 Offset,页面刷新后恢复
Topic 频道保证离线事件不丢失