Orisumi

Submission

平台 SDK 的登记、版本的状态、提交策略、发送与确认

程序实例通过所在运行环境的 SDK 把版本交给后端。Observer 的业务代码负责形成事实、维护身份和选择提交策略;SDK 负责本地保存、接好版本链、发送、确认和恢复。这样分工的理由见 ADR · 提交与 SDK。

分工

Observer 的业务代码SDK
定义 EntitySchema,识别对象,形成观测内容和 Observation登记程序实例和所需的 EntitySchema
决定粒度、身份和历史保留本地保存草稿和待发送的版本,接好版本链
选择提交策略,明确通知更新和结束按依赖顺序发送,处理确认、重试和恢复
处理被拒绝的版本把被拒绝的版本和原因交给业务代码

应用是否切换、事实是否仍在持续、被拒绝的版本怎样改写,都由业务代码判断。后端按 Schema 版本和 Core 的规则校验并保存。

接入

连接后端

业务代码提供后端地址。SDK 用 POST /versions 提交,按 API 组织请求、解析响应和错误;网络库和请求方式由各平台的 SDK 决定。

登记

启动时,业务代码把程序实例和所需的 EntitySchema 交给 SDK。SDK 先提交它们,再发送其他版本;网络不可用时,登记内容保存在本地,恢复后最先提交。程序实例的 EntityId 和 SchemaId 在重启后保持不变,SchemaId 是写在业务代码中的常量。程序实例的信息变化时,SDK 形成它的新版本,见 OBSERVER-4。

SDK 用 GET /entities/{entityId}/versions 读取 EntitySchema 的版本链。链中已有与业务代码给出的内容相同的 Schema 版本时,直接引用它;没有时,在当前版本之后形成新版本。内容是否相同按 API · 内容相同 判断。

例如两台设备上运行着新旧两个版本的前台状态 Observer,各自引用自己那一版 Schema,Schema 不会在两台设备之间来回改写。业务版本可以引用同一个 EntitySchema 中较旧的 Schema 版本,见 ENTITY-3。

版本的状态

前台状态 Observer 在 10:00 确认 VS Code 在前台,形成一份 Observation;10:05 再次确认,把结束边界延长到 10:05。这时这份 Observation 还没有发送,延长直接改写它在本地的内容,后端只会收到一个版本。版本一旦被别的版本引用或进入发送,就不再改写,之后的变化形成新版本。

状态含义SDK 怎样处理
草稿已本地保存,尚未发送,也没有被其他版本引用可以合并或丢弃
已冻结已被其他版本引用,或已进入发送按原样发送和重试
已保存后端已确认保存移出发送队列,保留它的 VersionId 供之后引用
被拒绝后端拒绝了它,并给出 rule交给业务代码,见被拒绝的版本
  • 新版本的 previousVersionId 指向这个实体在本地最新的版本,这个版本可以尚未保存。所以版本链在本地就已接好。
  • 合并是改写草稿的内容,草稿的 VersionId 和 previousVersionId 不变。
  • 业务代码引用一个实体时,SDK 给出这个实体在本地最新的版本,并冻结这个版本。
  • 冻结一个版本前,SDK 先冻结它引用的、仍是草稿的版本。所以冻结的顺序满足依赖顺序,SDK 按这个顺序发送,见 VERSION-13。

提交策略

同一个 Observer 可以对不同的业务类型选择不同的策略。两种策略都在数据形成时本地保存草稿,补全合并进草稿;区别在于草稿何时冻结。

策略何时冻结后端看到的版本
及时提交SDK 每次发送时冻结当前的草稿;之后的补全形成新的草稿每次发送一个版本,最后一个是最终结果
结束后提交业务代码通知结束时冻结只有最终结果

发送的时机不影响事实时间。

更新与结束

业务代码把新形成或补全的数据交给 SDK,并明确通知 SDK 一段事实何时结束。endAt 有值不能当作结束通知,因为它也可能只是最近一次确认的时刻,见 TIME-4。

例如 10:00 确认 Codex 在前台,10:05 再次确认,业务代码把同一份 Observation 补全到 10:05。10:08 切换应用时,业务代码才通知这一段结束,并为新应用形成新的观测。

发送与确认

本地保存与发送

SDK 先把版本保存在本地,再安排发送。它按冻结的顺序把版本分批发送,一批就是一次提交,大小在请求体的上限之内。发送失败或响应不确定时,版本留在本地,等网络恢复或程序重启后继续发送。

SDK 启动时恢复草稿、待发送的版本和待处理的被拒绝版本;退出前只需把已接收的内容保存到本地。

确认

SDK 按响应确认版本,不需要读回。

响应SDK 的处理
200这一批全部确认为已保存
400 或 409,带 index位置在 index 之前的版本确认为已保存;index 处的版本被拒绝;之后的版本确定没有保存,可以由业务代码改写
400,不带 index请求不符合契约,是 SDK 的错误:停止发送,报告给业务代码
413拆成更小的批,重新发送
5xx 或网络失败稍后原样重发

保存成功不代表这段事实已经结束,SDK 继续接收更新和结束通知。状态码和错误字段见 API · 错误格式。

重试

重试沿用原来的 VersionId,内容、引用和事实时间保持原样,见 IDENTITY-5。后端已保存但响应丢失时,SDK 原样重发,后端把已保存的版本直接确认,返回首次保存时的 recordedAt,见 VERSION-7。

被拒绝的版本

SDK 把被拒绝的版本、它的 rule,以及依赖它的待发送版本交给业务代码,处理完之前暂停发送。业务代码可以:

  • 丢弃这个版本,以及依赖它的版本;
  • 读取实体新的当前版本,基于它改写这个版本,以及依赖它的版本。

因 VERSION-6 被拒绝、而后端的当前版本与被拒绝的版本内容相同时,业务代码可以让 SDK 采用已保存的版本:SDK 把待发送版本中指向被拒绝版本的引用改为指向当前版本,再继续发送。例如同一台设备上的两个程序实例共用本机应用的登记文件,同时为同一个应用提交首版,后提交的一方采用先保存的首版。

400 带 rule 的拒绝说明版本本身违反 Core 规则,通常是业务代码的错误,需要修正后再处理。

发送状态

SDK 向业务代码报告待发送的数量、已确认的数据和被拒绝的原因,业务代码据此区分仍在本地、已保存和被拒绝的数据。

断网示例

前台应用采用及时提交时:

时刻发生的事SDK 的处理
启动程序实例和所需的 EntitySchema 已确定登记程序实例和 EntitySchema
10:00Codex 开始处于前台保存观测内容和 Observation 的草稿,安排发送
10:02网络中断已冻结的版本留在本地,之后的补全合并进新的草稿
10:08切换到浏览器冻结 Codex 的最终版本,为浏览器形成新的草稿
10:10网络恢复按冻结的顺序补交 Codex 的版本,以及浏览器截至最近一次确认的版本

如果采用结束后提交,Codex 的时段在结束时冻结并安排发送,浏览器的时段继续作为草稿补全,等业务代码通知结束。

平台实现

同一运行环境中的 Observer 共用该平台的 SDK。本地保存和后台任务的做法写在各平台的页面。

SDK本地保存
.NETSQLite

贡献者

页面历史