摘要

  • RFC 5267 把持续更新的搜索或排序定义成“初始答案 + ADDTO/REMOVEFROM 有序变更流”;这些变更带位置含义,并通过原命令标签归属到同一个上下文。
  • 规范明确说它不提供快照机制。服务器可用 NOUPDATE 拒绝持续更新,CANCELUPDATE、邮箱取消选中、断线或无法解释的传输缺口都会终止连续性。

“还在动”不等于“没有漏”

实时界面最容易制造一种错觉:只要它刚刚动过,就一定掌握了现在。新邮件出现,旗标变化后某行消失,计数也跟着更新;屏幕把这些动作压成一个平滑的“实时搜索”。但平滑只证明渲染层收到过变化,不能证明此前每一个变化都完整到达。

RFC 5267 允许 SEARCH、UID SEARCH、SORT 或 UID SORT 请求 UPDATE。服务器先给出初始结果,之后通过 unsolicited ESEARCH 发送 ADDTO 与 REMOVEFROM。响应中的 correlator 指回创建上下文的原命令标签。每一条变更都是对那次具体查询、标识符模式和排序方式的维护指令,不是可以随意搬到相似列表上的通用事件。

规范对边界说得很直白:不存在 snapshot facility。CONTEXT 只是一项提示,服务器可以据此维护缓存或索引,也可以忽略;有没有内部缓存,不得改变外部行为。因此客户端能证明的不是“服务器替我保存着一张照片”,而是“我保存了起点,而且没有漏掉此后的任何合法补丁”。

ADDTO 与 REMOVEFROM 是位置敏感的补丁语言

ADDTO 给出上下文位置以及应插入的结果;REMOVEFROM 给出位置以及从那里移出的结果。普通 SEARCH/SORT 使用消息序号,UID 版本使用 UID。这里的“位置”使操作顺序成为语义的一部分。

RFC 5267 要求客户端严格按出现顺序处理 ADDTO 和 REMOVEFROM,包括同一 ESEARCH 响应内的多项;服务器也必须生成能按此顺序维持请求排序的补丁。先删后插与先插后删可能产生不同列表。把这些消息并行投递,再按本地时间戳排序写回,并不能恢复协议规定的顺序。

最低限度的审计对象应包括:完整查询、UID 或序号模式、请求的排序、原命令标签、初始有序结果,以及单调保存的接收次序。活动上下文的标签不能拿来创建另一个更新上下文,否则服务器应返回 BAD。标签不是装饰,它是 unsolicited 变更能够归因到正确问题的键。

EXISTS 与 EXPUNGE 划定序号的有效时刻

消息序号会因 expunge 而重排。若新投递或 append 造成带序号的 ADDTO,服务器必须先发送 EXISTS,之后那些新序号才有效。若 expunge 造成带序号的 REMOVEFROM,服务器必须在 EXPUNGE 之前发送它,因为旧序号只有那时还保留原义。

所以 EXISTS、FETCH、ESEARCH 与 EXPUNGE 必须进入同一条接收顺序日志。将它们分送不同队列,再靠各服务的墙上时钟拼回去,会丢掉因果约束。ESEARCH 还可以在没有命令执行时、处理别的命令时或 IDLE 期间到达;只记录成对请求与完成响应的监控方式,恰好会漏掉维护上下文的 unsolicited 数据。

查询条件本身若使用消息序号,也有独立边界:这些序号在服务器收到命令时求值。以后重排导致同一个数字指向别的消息,不会仅因此发出更新。拿旧查询文本在新邮箱状态上重新解释,是另一次查询,不是旧上下文的延续。

NOUPDATE:结果有效,持续承诺却不存在

服务器可能因内部上下文达到上限而拒绝更新。它会发送未标记的 NO,并以 NOUPDATE 和原搜索标签说明拒绝对象;其他 return options 仍必须得到满足。

这会形成一个很危险、却完全合规的状态:初始搜索结果可用,命令也能正常结束,但服务器没有接受持续维护。如果解析器保留结果行、丢掉 NOUPDATE,静态答案就会穿上“实时”外衣。

规范要求每个客户端至少可获得一个更新上下文,并建议提供更多;它也承认维护已排序上下文通常更昂贵,因此 SORT 被拒不表示普通 SEARCH 也必然被拒。客户端可以降级、重试或改成静态显示,却不能掩盖拒绝。运行状态至少应区分请求、接受、拒绝、活动、取消、因取消选择而结束,以及连续性未知。

PARTIAL 只裁剪画面,不裁剪更新责任

PARTIAL 返回有序结果中的一个位置窗口,很适合虚拟列表。但 UPDATE 与其他 return option 不相互限制。UPDATE 和 PARTIAL 同时使用时,服务器仍可能通知当前窗口之外的匹配变化;MIN、MAX、COUNT 也不会把更新范围缩成一个摘要值。

若前端只维护屏幕上几十行,并丢弃“暂时看不到”的补丁,下一次窗口位置就失去了依据。系统可以选择不保存完整上下文,但那就必须宣布上下文失效并重新取得基线。可视窗口只是投影,不是权威边界。

连续性终止后,后续消息不能自行补洞

邮箱不再选中,或客户端针对原标签发送 CANCELUPDATE,更新便停止,服务器也可以释放资源。重连、重新 SELECT、用相同条件再搜一次,产生的是新观察,不会复活旧流。

显式断线容易发现;更危险的是解析器漏掉一项、背压队列丢消息,或自动重连后继续沿用旧组件状态。只要有一个位置补丁可能缺失,后来收到再多补丁也不能证明列表已恢复。位置流不会因为继续流动就自愈。

RFC 7162 的 CONDSTORE/QRESYNC 提供另一套带前提的重新同步机制;IDLE 便于接收 unsolicited response;NOTIFY 表达事件兴趣。它们都不会仅凭“服务器支持”自动修补破损的 RFC 5267 上下文。客户端必须真正执行对应流程、验证结果并建立新基线。

按照 Running-Code Primacy,应受管理的不是“实时搜索”这个产品名,而是实际运行的命令、能力代际、选中邮箱、初始结果、有序补丁和终止边界。初始观察、UPDATE 获准、重建列表、可视页面与用户动作属于不同现实层。只有当每一行都能反查到上下文标签、标识符模式和接收次序时,界面才有可逆的证据;否则它只是流畅的画面。

来源