如何允许同时只有一个 onUpdate 函数访问文档?
How to allow an access to the document for only one onUpdate function at the same time?
我有一个应用程序,每个销售都在 Tracking
集合中注册为文档。
另一个集合是Actuals
。每个用户都有当月的 totalValue
字段的存储文档。
TotalValue
以这种方式计算 - 当添加或修改销售时(onCreate / onUpdate 函数)字段 totalValue
的值是从文档中获取的,它是计算的(例如增加 100,因为添加了价值 = 100 的新销售),然后用新值推回该文档。 (事实上,还有很多其他字段需要计算,我正在更新整个文档,但让我们举个例子,仅包含 totalValue
。)
代码如下所示:
exports.updateActuals = functions.region(util_1.getFunctionRegion()).firestore
.document(`${trackingCollectionName}/{id}`)
.onUpdate((change) => {
const service = new TargetService();
if (<TrackingDto>change.after.data().isDeleted) {
return service.getAndDeleteFromActuals(change.before.id, <TrackingDto>change.before.data())
.then((actual: ActualsDto) => admin.firestore().doc(`${actualsCollectionName}/${actual.id}`).set(actual.data))
.catch(er => error(er))
} else {
return service.getAndUpdateActuals(change.before.id, <TrackingDto>change.after.data(), <TrackingDto>change.before.data())
.then((actual: ActualsDto) => admin.firestore().doc(`${actualsCollectionName}/${actual.id}`).set(actual.data))
.catch(er => error(er));
}
});
如果用户在在线模式下工作,这个 onUpdate 函数就像一个魅力。
当用户在离线模式下工作时会出现此问题。当他切换回在线模式时,他在离线模式下所做的所有销售都将发送到 firebase。因此,例如,那些注册的销售将同时触发 10 个 onUpdate 函数。这意味着他的“Actuals”集合中的文档将由 10 个 onUpdate 函数进行编辑。这会导致计算错误,因为它们共享相同的值(totalValue 字段)。
问题示例:
- ...
- 总价值 = 100
- onUpdate_1取totalValue=100加10
- 总价值 = 110
- onUpdate_2 取 totalValue=110 加 20
- onUpdate_3取totalValue=110加30
- 总价值 = 140
- ...
有没有办法强制 onUpdate 等到特定文档不被使用或延迟将销售文档添加到 firebase(但不是作为应用程序端的线程)?还有其他选择吗?
如果字段的新值取决于其当前值,您应该始终use a transaction - or an atomic increment operation以防止出现现在的问题。
在这种情况下,我会使用 admin.firestore.FieldValue.increment(10)
,它确保数据库本身将读取-递增-写入值,从而防止您现在看到的问题。
您 可以 还通过 setting maxInstances
in your code.[=14= 告诉 Cloud Functions 永远 运行 一次 Cloud Functions 实例多次]
我有一个应用程序,每个销售都在 Tracking
集合中注册为文档。
另一个集合是Actuals
。每个用户都有当月的 totalValue
字段的存储文档。
TotalValue
以这种方式计算 - 当添加或修改销售时(onCreate / onUpdate 函数)字段 totalValue
的值是从文档中获取的,它是计算的(例如增加 100,因为添加了价值 = 100 的新销售),然后用新值推回该文档。 (事实上,还有很多其他字段需要计算,我正在更新整个文档,但让我们举个例子,仅包含 totalValue
。)
代码如下所示:
exports.updateActuals = functions.region(util_1.getFunctionRegion()).firestore
.document(`${trackingCollectionName}/{id}`)
.onUpdate((change) => {
const service = new TargetService();
if (<TrackingDto>change.after.data().isDeleted) {
return service.getAndDeleteFromActuals(change.before.id, <TrackingDto>change.before.data())
.then((actual: ActualsDto) => admin.firestore().doc(`${actualsCollectionName}/${actual.id}`).set(actual.data))
.catch(er => error(er))
} else {
return service.getAndUpdateActuals(change.before.id, <TrackingDto>change.after.data(), <TrackingDto>change.before.data())
.then((actual: ActualsDto) => admin.firestore().doc(`${actualsCollectionName}/${actual.id}`).set(actual.data))
.catch(er => error(er));
}
});
如果用户在在线模式下工作,这个 onUpdate 函数就像一个魅力。 当用户在离线模式下工作时会出现此问题。当他切换回在线模式时,他在离线模式下所做的所有销售都将发送到 firebase。因此,例如,那些注册的销售将同时触发 10 个 onUpdate 函数。这意味着他的“Actuals”集合中的文档将由 10 个 onUpdate 函数进行编辑。这会导致计算错误,因为它们共享相同的值(totalValue 字段)。 问题示例:
- ...
- 总价值 = 100
- onUpdate_1取totalValue=100加10
- 总价值 = 110
- onUpdate_2 取 totalValue=110 加 20
- onUpdate_3取totalValue=110加30
- 总价值 = 140
- ...
有没有办法强制 onUpdate 等到特定文档不被使用或延迟将销售文档添加到 firebase(但不是作为应用程序端的线程)?还有其他选择吗?
如果字段的新值取决于其当前值,您应该始终use a transaction - or an atomic increment operation以防止出现现在的问题。
在这种情况下,我会使用 admin.firestore.FieldValue.increment(10)
,它确保数据库本身将读取-递增-写入值,从而防止您现在看到的问题。
您 可以 还通过 setting maxInstances
in your code.[=14= 告诉 Cloud Functions 永远 运行 一次 Cloud Functions 实例多次]