摘要

  • RIPE 数据库允许同一更新消息里的对象得到不同结果。整体标为失败,并不意味着已成功的修改被一并撤销。
  • Syncupdates 的 HTTP 连接中断后,数据库仍可继续处理请求。调用方没收到最终回复,首先意味着结果尚未确认,而不是所有操作都没发生。
  • 回执中的逐项结果、事后的获授权查询、不同收件人收到的通知各有范围。恢复工作的起点应是保留并核对这些区别,而不是把整个批次重新执行一次。

五个对象,并不是五次同样的行动

RIPE NCC 的回执指南给出过这样一组示例数字:数据库识别出五个对象,四项处理成功,一项失败。再往下读,四项成功又分成一次创建、两次修改和一次无须改变;失败的是另一项修改。

因此,“四项成功”并不表示改了四个对象。示例里真正产生变化的是一次创建与两次修改,剩下那次成功只是确认提交内容已经与库中内容相同。按照同一指南对邮件式总结果的定义,只要存在失败项,整个消息就会被归为 FAILED。这个总结果与三项已经完成的变化并不冲突。

这里讨论的是官方文档中的解释性示例,不是对客户账户的观察,更不是一次事故的记录。页面上另外展示的主题行和报文片段,也不能拼起来冒充一份完整的真实回执。值得注意的是文档明确表达的语义:总结果、逐项结果和实际变化数量,并不是一回事。回执指南

这一区别会直接改变下一步工作。被拒绝的修改可能需要补全资料;已经一致的对象可能完全不用动;成功的修改也许就是原计划希望得到的状态。如果一个工具把它们全部压成“失败,等待重试”,它丢掉的不是装饰信息,而是恢复操作需要的依据。

同一个信封,不保证同一个结局

RIPE 数据库的处理说明以对象为单位。一个对象没有通过检查,不会自动令后面的对象停止处理。不过,独立处理不等于没有依赖。如果先前创建某个被引用对象的操作失败,后续依赖它的对象也可能因为引用不存在而失败。AUTO-n 自动生成标识的引用还可能改变处理顺序,不能把提交文件的排列一律当成严格执行顺序。对象处理规则

这种安排有合理之处。某项更新有格式问题,不一定值得阻止同一消息里另一项合法、有效且无关的维护。逐对象验证仍然可以检查授权和引用完整性。让所有对象必须一起提交、一起撤销,是另一种服务承诺,不是把请求放进同一个消息就自然获得的性质。

从组织的角度看,问题又不同。工作人员可能把几条记录的调整视为一次完整交接,而服务器只负责判断每条对象操作能否成立。两种完成标准并不相同。数据库不能从一个容器里自动推断:这家公司认为哪几项缺一不可,哪几项可以各自完成,以及出现部分结果时应该保留什么。

这也使责任变得具体。RIPE NCC 需要把自己实际处理的结果说清楚;使用它的工具则需要保留足够信息,使组织能够判断业务上的工作是否完成。当前回执已经把失败、成功和未被识别成对象的内容分别列出。首先用好这些既有信息,比另造一种泛化的“成功证明”更有意义。

没收到答复,是一种尚待确认的状态

Syncupdates 可以在一次请求中接收多个对象,并把处理结果一并交回调用者。它面向能够继续解析结果的应用,而不只是把内容送出去的程序。回执指南特别区分 HTTP 层与对象层:这个接口的 HTTP 200 可以表示请求已经得到处理,却不能据此认定里面所有对象操作都成功了。Syncupdates 说明

更容易在交接时丢失的信息,是根本没有收到回复的情况。文档说明,连接超时或关闭,并不会自动取消服务器正在进行的处理。服务器可以继续做完检查和操作,只是无法再把最终回执通过那条已经关闭的连接送回来。这里的“继续处理完”仍不等于每个对象都通过了检查。

假设某个维护程序断线后只留下一个红色任务条。第二位工程师接手时,看到的只是本地任务失败,并不知道服务器在哪一步停下了回复,也不知道各对象的结果。若直接把状态改成“均未执行”,就是补上了一条现有证据并没有提供的结论;若改成“均已成功”,同样如此。

更诚实也更有用的做法,是让尚未确认的操作暂时保持未知,再通过有权使用的查询、保存下来的逐项信息或必要的支持流程核对。未知不是一个需要尽快涂成红色或绿色的界面缺陷,它是下一步调查的范围。

本研究没有向 RIPE 数据库提交更新,也没有故意中断连接、使用客户凭据或统计超时概率。上面的交接情景用于解释文档规则的含义,不说明任何一家运营者已经遭遇了这种问题。

为什么同事收到邮件,仍不能替整批操作作证

通知邮件有助于解释变化,但不是原始回执的完整副本。RIPE 的通知机制根据对象及其引用中的通知属性确定收件人;同一批更新里,不同邮箱可能只收到与自己相关的不同对象。因此,一封内容准确的通知,也可能只覆盖提交者维护任务的一部分。通知规则

修改通知地址时,这种范围尤其需要看清。文档规定,对象被修改时,notify: 这一属性使用旧版本中的地址。其他属性或引用仍可能带来其他通知路径。不能据此断言新地址绝不可能收到任何邮件;但也不能仅凭新提交的地址,就推断谁应该拥有这一批操作的完整结果。

成功修改产生的普通通知,与授权验证失败后面向相关安全联系人的通知,原因也不同。收到了邮件,不自动等于批准过操作;没收到邮件,也不能证明没有任何对象发生变化。本文没有测试邮箱投递是否成功,不能把通知生成规则扩写成送达率结论。

让所有收件人都收到整个请求,并不是当然更好的解决办法。一个维护者需要知道自己负责的对象发生了什么,却未必有权看到同批其他对象的联系信息。完整性必须相对于读者的职责来判断,而不是把更多披露一概当成更强证明。

核对现状,不等于抹掉先前结果

RESTful API 提供按对象定位的操作和结构化响应,与 Syncupdates 的消息式接口不同。选择它可以改变应用处理单项结果的方式,却不会让若干独立请求自动成为一个原子事务。组织想完成的多记录工作,仍需要明确哪些结果算完成。RESTful API 文档

查询本身也有时点。REST 文档区分了更新响应与稍后通过查找或搜索看到新状态,中间可能存在延迟。刚提交完就看到旧值,单凭这一点不能宣布更新已回滚。应遵守所用接口的观察规则,而不是靠高频反复查询替代判断。这里没有测量延迟,更没有承诺一个适用于所有对象的等待秒数。

事前 dry-run 能减少另一类不确定性:它检查格式、业务规则、授权和引用完整性,但不写入数据库,也不发送普通变更通知。这种验证很有价值,却不是未来真实执行的保留名额,也不能证明之后那次操作已经发生。Dry-run 说明

收到混合结果或丢失回复后,可以先做一份很小的核对记录:本来想对哪个对象做什么、已收到的逐项结果是什么、哪些仍然未知、后来观察到什么,以及下一步为何需要或不需要操作。原始响应应在适当权限下保存,供后续判断引用;导出工作记录时,不应把凭据或不必要的个人联系信息一起带出去。

这并不是说所有重试都有害。如果授权与意图没有变化,而对象已经与提交内容相同,再次得到无变化结果完全可能是合理的。真正应避免的,是尚未核对原请求的结果,就把整批操作视为待重新开始。尤其不能为了关闭旧任务,顺手抹去后来另一位获授权人员作出的有效修改。

历史查询也不能包办重建。文档说明可以访问对象的旧版本,但个人历史数据不提供这种查询。公开历史中的缺口,不等于 RIPE NCC 内部不存在记录;它只是提醒使用者,不能假定将来总能从公开接口重新拼回自己曾收到的一切。历史数据说明

数据库维护最终需要回答的,是哪些工作还有必要继续,而不是怎样让一个状态栏更快变色。逐对象处理可以是合理设计,整体失败也可以是准确提示。只有把已经完成、明确拒绝、无须变化和尚未确认分开,下一位负责人才能在已有成果上继续,而不是从一个错误的“全部未做”重新出发。

来源

  1. RIPE NCC:更新回执
  2. RIPE NCC:对象处理
  3. RIPE NCC:Syncupdates
  4. RIPE NCC:通知消息
  5. RIPE NCC:RIPE 数据库 RESTful API
  6. RIPE NCC:Dry-run
  7. RIPE NCC:历史数据