captureCrudWrite()
function captureCrudWrite<TResult>(
port,
token,
write,
businessWrite
): Promise<TResult>;
Defined in: packages/rxdb-plugin-working-tree/src/working-tree/write-entry.ts:448
把一次普通 CRUD 写入包进工作树捕获的四步(FR-039)
Type Parameters
| Type Parameter | Description |
|---|---|
TResult | 业务写入的返回类型 |
Parameters
| Parameter | Type | Description |
|---|---|---|
port | WorkingTreeCapturePort | 捕获端口,由调用方绑定到当前事务 |
token | ActiveBranchToken | 调用方在读取 / 实例化实体时捕获的 active 分支 token |
write | CapturedWrite | 这一次要捕获的写 |
businessWrite | () => Promise<TResult> | 尚未执行的业务写入 |
Returns
Promise<TResult>
businessWrite 的返回值,原样透传
Throws
StaleActiveBranchError token 过期;此时 businessWrite 一次都没被调用
Remarks
四步顺序即契约:校验 token → 写业务实体 → 写入或合并完整单元 → 递增 workingTreeRevision。
调用方必须把这四步放在同一个事务里,任一步失败全部回滚。
三处顺序不能调换:
- token 校验在业务写入之前。 挪到后面就成了「先写进去再发现分支不对,靠回滚收拾」。 raw 通道与批量写路径都已经为「拒绝发生在执行前」付过代价,最热的 CRUD 这条路没有理由退让。
- 递增排在落条目之后。 反过来的话,条目写失败时 revision 已经 +1——而它是 commit 的 CAS
依据,一次失败的
save()会让另一个 Tab 手里的 revision 凭空作废。 - 读已有条目在落条目之前,且读的是库不是内存 dirty set。刷新一次页面 dirty set 就是空的,
于是
inversePatch被记成刷新后的值,discard 从此退不回 HEAD,全程没有任何报错。
entryCount 的增量原样取自折叠(foldWorkingTreeEntry),捕获不自己数:
数第二遍就是第二份真相,而且是没有用例保护的那份。
Example
await adapter.transaction(async tx => {
const port = createCapturePort(tx);
return captureCrudWrite(port, entity.branchToken, toCapturedWrite(entity), () => tx.upsert(entity));
});