跳到主要内容

allocateBranchGeneration()

function allocateBranchGeneration(executor): Promise<number>;

Defined in: packages/rxdb-plugin-working-tree/src/working-tree/activation-state.ts:248

发放下一个分支代际:让库把 branchGenerationSeq 就地 +1,再把新值读回来。

Parameters​

ParameterTypeDescription
executorTransactionExecutor调用方那个写事务的执行器;发放与新分支落库必须同属一个事务

Returns​

Promise<number>

本次发放的代际号,首次发放为 1

Throws​

RxDBError 单例行不存在、或不止一行(rowsAffected !== 1)时

Remarks​

加法在库里做,不在 JS 里做(见 buildBranchGenerationAdvance)。这里曾经是一次 同事务内的读—改—写,靠一句「本地写队列并发度为 1,同事务内的读—改—写因此是原子的」自辩; 那句话把「一个库只有一个连接在写」当成前提,而 git show f9528e8f:specs/001-working-tree-commits/threat-model.md §6 已经把跨连接明确划进模型内——同一个库可以有第二个标签页、第二个 worker 在写,写队列只排得住自己进程里的那些。

返回值现读库,不是 读到的 + 1。 读回来那一次落在同一个事务里,它看得见自己刚写下的 那一步加法;并发的第二条发放此刻正卡在这一行的行锁上(SQLite 家族则整条写事务串行), 所以读回来的就是本次发放到的号。省掉这次读、在 JS 里算一个数出来的话,前面那条 UPDATE 就白发了——号仍然是调用方算的。

读回来那一次也走原始语句(buildBranchGenerationRead),不走仓库:仓库交出的是 身份映射里的实体实例,它看不见上一条原始 UPDATE,回填时反而会把 branchGenerationSeq 当成「本地未保存的编辑」保护下来。两条语句因此都落在同一条通道上——加法在库里做, 号也从库里取,中间没有一层会替它记答案的缓存。

rowsAffected !== 1 当场抛,不静默走过去,理由与 readWorkingTreeActivationState 的缺行抛错同源,代价更重:带着一个不可信代际落库的新分支,会让持旧 (branchId, headRevision) 的调用方误中同名重建的那一条(ABA),提交幂等键跟着一起失效(commit-idempotency.ts), 而这一次撞号在建分支的那一刻是完全静默的。