【发布时间】:2020-03-16 17:12:41
【问题描述】:
在我的(非常简化的)模型中,我有用户、帐户和 account_types。每个用户可以拥有每个 account_type 的多个帐户。创建 TT 类型的帐户后,我将更新该对象的“用户”字段,以便保留拥有该类型帐户的用户以及他们拥有的此类帐户的数量。
users: {
some fields
},
accounts: {
userID: UU,
type: TT
},
account_type:
users: { UU: 31 }
}
我使用帐户的 onCreate 和 onDelete 云触发器来更新 account_type 对象。由于可以同时创建多个帐户,因此我必须使用事务:
exports.onCreateAccount = functions.firestore
.document('accounts/{accountID}')
.onCreate((account, context) => {
const acc_user = account.data().userID;
const acc_type = account.data().type;
return admin.firestore().runTransaction(transaction => {
// This code may get re-run multiple times if there are conflicts.
const accountTypeRef = admin.firestore().doc("account_types/"+acc_type);
return transaction.get(accountTypeRef).then(accTypeDoc => {
var users = accTypeDoc.data().users;
if (users === undefined) {
users = {};
}
if (users[acc_user] === undefined) {
users[acc_user] = 1;
} else {
users[acc_user]++;
}
transaction.update(accountTypeRef, {users: users});
return;
})
})
.catch(error => {
console.log("AccountType create transaction failed. Error: "+error);
});
});
在我的测试中,我首先使用一些数据填充数据库,因此我还添加了一个用户和 30 个相同类型的帐户。使用本地模拟器,这工作得很好,在添加结束时,我看到 account_type 对象包含计数器为 30 的用户。但是当部署到 Firebase 并运行相同的功能时,计数器会小于 30。我的怀疑是因为 Firebase 速度慢得多,事务需要更长的时间,所以它们中的更多是冲突和失败的,最终根本不执行。交易失败文档 (https://firebase.google.com/docs/firestore/manage-data/transactions) 说:
“事务读取了在事务之外修改的文档。在这种情况下,事务会自动再次运行。事务会重试有限次。”
所以我的问题:
- “有限”是什么意思?
- 有什么方法可以控制这个数字?
- 如何确保我的事务在某个时间点被执行并且不会像那样被丢弃,从而使我的数据保持一致?
- 关于为什么我在部署到云时没有得到正确结果的任何其他想法?
【问题讨论】:
-
我测试了您的云功能,确实有时您需要等待几分钟才能正确更新计数器。我们清楚地看到计数器更新是在“波”中执行的。你应该看看分布式计数器:firebase.google.com/docs/firestore/solutions/…
-
另请注意,您可能会在 Cloud Functions 控制台中收到与此类似的错误消息:
Error: quota exceeded (Quota exceeded for quota group 'FunctionCallsNonbillable' and limit 'Function invocations per 100 seconds' of service 'cloudfunctions.googleapis.com' for consumer 'project_number:xxxxxx'.); to increase quotas, enable billing in your project at https://console.cloud.google.com/billing?project=xxxxxx. Function cannot be executed.。所以你可能需要切换到 Blase 计划。
标签: arrays firebase google-cloud-firestore transactions google-cloud-functions