分页
如何用一个不透明游标走完任意一个集合,以及如何让一份副本保持最新。
这个 API 里的每一个列表都以同样的方式读取:你一页一页地走完一个 集合,收货记录也不例外。
GET /v1/restaurants/{restaurantId}/collections/{collection}/records
?limit=100
&cursor=eyJpZCI6…
| 参数 | 必填 | 规则 |
|---|---|---|
limit | 否 | 1 到 100。默认 50。 |
cursor | 否 | 上一页的 nextCursor,一字不改地传回。 |
返回的是 { "data": [...], "nextCursor": string | null }。
没有时间区间
没有 from,也没有 to。一条记录会原地改变(一次更正、一条 tombstone),所以你
走完这个集合然后对账,而不是去要它的某一段窗口。要读一周的收货记录,就遍历
deliveries,留下 data.timestamp 落在那一周之内的记录。
排序
最早的改动在前:按 sequence 升序,也就是每条记录最近一次改动在变更流中的位置。
拿两个 sequence 来比较;不要拿一个去做算术。
逐页走完
nextCursor 在最后一页是 null,其他情况下是一个字符串。原封不动地把它传回去:
它是一个不透明的位置,不是一份供你解析的文档,它的内部结构会在不另行通知的情况下
改变。
async function* records({ apiKey, restaurantId, collection }) {
const base = `https://api.backresto.com/v1/restaurants/${restaurantId}/collections/${collection}/records`;
let cursor = null;
do {
const url = new URL(base);
url.searchParams.set('limit', '100');
if (cursor !== null) {
url.searchParams.set('cursor', cursor);
}
const response = await fetch(url, {
headers: { Authorization: `Bearer ${apiKey}` }
});
if (!response.ok) {
throw new Error(`BackResto ${response.status}`);
}
const page = await response.json();
yield* page.data;
cursor = page.nextCursor;
} while (cursor !== null);
}
一次遍历就是一份一致的快照。 第一页把这条变更流的位置钉住,之后的每一页都按 同一个位置作答。你在翻页期间写入的记录不会让页在你脚下移位。你会在下一次遍历时 看到它们。
游标绑定到餐厅、集合以及那个 limit。在一次遍历中途更改每页大小会返回 400:
选定一个 limit,整趟遍历都别改。
让一份副本保持最新
今天还没有 since 参数。一次刷新就是又一次遍历,然后你拿它和已经持有的数据对账:
- 在一个集合内以
id为键,当收到的sequence高于你存下的那个时就覆盖。 - 认真对待 tombstone。
deleted: true就是那条删除指令;照做是让你的副本不再 越跑越偏的唯一办法。 - 预料到迟到的记录。 一台在营业期间离线的设备会在重新联网时上传,所以一条记录
可能在一次本应覆盖它
data.timestamp的遍历之后才出现。用capturedAt做报表, 用receivedAt做同步。
一页空数据并不能证明什么都没发生。见 关于完整性的说明。