withTriggersDisabled()
function withTriggersDisabled<T>(
adapter,
tx,
body
): Promise<T>;
Defined in: packages/rxdb-adapter-sqlite-core/src/version/with_triggers_disabled.ts:88
在触发器停用的窗口内执行一段写入:删触发器 → 跑 body → 重建触发器。
Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type | Description |
|---|---|---|
adapter | RxDBAdapterSqliteBase | SQLite 适配器 |
tx | SqlExecutor | 当前事务的执行器;三明治的三步必须落在同一事务里 |
body | () => Promise<T> | 窗口内要执行的写入,返回值原样透传 |
Returns
Promise<T>
body 的返回值
Throws
原样重抛 body 的错误——body 抛错但触发器重建成功时
Throws
RxDBAdapterSqliteError 触发器重建阶段读不到当前分支时抛出(不论 body 是否成功,见下)
Throws
AggregateError body 与触发器重建都失败时抛出:errors 为
[bodyError, restoreError],cause 为 bodyError
Remarks
用于「把远端副本抄进本地表」的路径:拉取回填与 QueryCache 的缓存写入都不是本地变更,
不该进 rxdb_change。表上的 AFTER INSERT/UPDATE/DELETE 触发器不区分写入来源,
唯一的抑制手段就是在写入期间把它们摘掉。
三步必须与写入同事务:拆成两次 runInTransaction 会在 C2 嵌套事务下自死锁
(见 readCurrentBranchId 的说明),而且中间那个没有触发器的已提交窗口会对并发写敞开 ——
那些写入的历史将永久丢失。
重建复用 generateSwitchBranchSql("切到当前分支"),因此它捎带的分支表 UPDATE 是
恒等写:RxDBBranch 自身 log: false,不会因此产生变更行。
重建触发器是「不论成功失败都必须跑」的收尾,且不用 try/finally 实现:本函数的生产
调用点都在 this.transaction() 里,body 抛错时整个事务连带回滚,中间那个「触发器已删、
还没重建」的状态从未真正提交过;但本函数经 src/index.ts 公开导出,第三方在事务外调用、
body 抛错时,这个中间态是真实会提交的——库从此永久没有触发器,且没有任何报错提示。
若改用 try { ... } finally { await restoreTriggers(); },finally 块里一旦再抛错
(重建本身失败),会按 no-unsafe-finally 描述的语义吞掉 try 块的完成状态,
body 的原始错误就此彻底消失、无迹可寻。这里改用「先捕获 body 的结果,再无条件跑一遍
收尾,最后按两者结果决定抛什么」的写法:与
packages/rxdb-test/src/encrypted/temporary-value.ts 的 withTemporaryValue 同构
——该函数解决的是结构相同的问题(跑主操作 → 无条件跑一个「必须执行」的收尾 →
两个都失败时用 AggregateError 保留两边),这里直接沿用同一套形状与措辞风格。
Example
await adapter.runInTransaction(
tx => withTriggersDisabled(adapter, tx, () => writeRemoteRows(tx, rows)),
false
);