02 带游标轮询与客户端感知


02 带游标轮询与客户端感知

本节摘要:第 01 节讲了事件怎么生成并存入存储,这一节讲客户端如何「感知」这些事件。OpenWork 用的是带游标(cursor)的轮询——客户端定期用一个端点拉取「上次游标之后的新事件」,靠游标保证不丢。本节讲清这套机制:为什么用轮询而非服务器推送、游标如何防丢、轮询的节奏。

一、为什么用轮询(而非 SSE/WebSocket)

先澄清一个常见误解——很多人以为「实时性」就得用 SSE(服务器推送事件)或 WebSocket(双向长连接)。OpenWork 的 Reload 事件用的是普通轮询。为什么?

轮询的优势在这套场景里:

  • 实现简单:就是个普通 HTTP GET 端点,客户端定期调。不用维护长连接、不用处理断线重连。
  • 中间件友好:轮询是普通 HTTP 请求,过负载均衡、代理、CORS 都没问题。长连接在这些环节容易出问题。
  • 无连接负担:服务器不用维持大量长连接(每个客户端一个),省资源。
  • 够用:Reload 不要求毫秒级实时,秒级延迟完全可以接受(改了技能,几秒后生效没关系)。

💡 「实时」不等于「推送」:很多场景轮询就够,而且更简单可靠。OpenWork 选择轮询,是务实的工程取舍——不为「看起来实时」而引入长连接的复杂度。

二、事件端点:拉取增量

服务端提供一个事件端点(如 GET /workspace/:id/events),客户端调它拉取事件。返回大致:

{ items: [事件1, 事件2, ...], // 新事件 cursor: 当前 seq, // 让客户端下次用 workspaceId: ..., disabled: false } ​

关键点是 cursor——它是「当前最新的 seq」。客户端下次请求时带上这个 cursor,服务端就只返回「cursor 之后」的事件(增量)。

三、游标(cursor):防丢的关键

游标是这套轮询的核心。它保证不丢事件:

第一次请求(无 cursor): │ ▼ 返回所有现存事件 + 当前 cursor(假设 seq=10) │ 客户端记下 cursor=10 │ ▼ 一段时间后,第二次请求(带 cursor=10) │ ▼ 服务端返回 seq>10 的事件(增量)+ 新 cursor(假设 seq=15) │ 客户端记下 cursor=15 │ ▼ 第三次请求(带 cursor=15) ... ​

游标的本质是「我上次读到哪了」——客户端每次告诉服务端「我从 seq=N 之后要」,服务端返回 N 之后的。这样即使两次轮询之间发生了多个事件,也一个不丢(全在增量里)。

⚠️ 环形缓冲的限制:第 01 节说事件存储是环形缓冲(只留最近 N 条)。如果客户端两次轮询间隔太久,中间事件可能已被挤出缓冲——这时客户端会「丢事件」。但 Reload 场景下这不是大问题(旧 Reload 错过了,下次全量重载补上)。设计是务实的——不追求「绝不丢」,只追求「正常情况下不丢」。

四、轮询的节奏

客户端怎么决定「何时轮询」?常见策略:

  • 固定间隔:每 N 秒(如几秒)轮询一次。简单,但空闲时也轮询(浪费)。
  • 指数退避:有事件时高频轮询(快速跟进),无事件时逐渐降低频率(省资源)。
  • 自适应:根据事件频率动态调整。

OpenWork 的前端有一个专门的轮询器(如 session-group-event-poller),负责按某节奏轮询事件端点,拿到事件后分发给相关方处理。

五、轮询的额外事件端点

除了工作区级的事件端点,还有几个相关的:

  • 会话级的事件(某个会话的变更)
  • 会话组(session-group)的事件

这些端点形态类似(返回 items + cursor),只是作用域不同。客户端按需订阅不同作用域的事件。

六、感知后的处理

客户端拿到事件后,做什么?这是下一节(引擎重载触发链)的主题。简单说:

客户端拿到 Reload 事件 │ ▼ 判断是什么 reason(config? skills? ...) │ ▼ 触发对应的重载动作 │ ▼ 驱动引擎重建实例、重读配置 ​

本节只讲「怎么感知」,下一节讲「感知后怎么办」。

七、本节要点回顾

  1. 用轮询而非推送:实现简单、中间件友好、无连接负担、够用——务实取舍。
  2. 事件端点:GET /workspace/:id/events,返回 items + cursor。
  3. 游标防丢:客户端带 cursor 要「增量」,服务端返回 cursor 之后的事件。
  4. 游标本质:「我上次读到哪」,即使中间多个事件也一个不丢。
  5. 环形缓冲限制:间隔太久可能丢旧事件,但下次全量重载补上——务实。
  6. 轮询节奏:固定间隔/指数退避/自适应,前端有专门轮询器。
  7. 多个事件端点:工作区级、会话级、会话组级,形态类似作用域不同。

感知讲清了,下一节讲感知后怎么办——引擎重载触发链。


作者与出处
原作者: 灏天文库
来源:different-ai
许可证:MIT
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: 灏天文库 转发
评论区 (0)
U