arrays - 不可靠的 Google Firebase 交易
问题描述
在我的(非常简化的)模型中,我有用户、帐户和 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)说:
“事务读取了在事务之外修改的文档。在这种情况下,事务会自动再次运行。事务会重试有限次。”
所以我的问题:
- “有限”是什么意思?
- 有什么办法可以控制这个数字?
- 我怎样才能确保我的交易在某个时候被执行并且不会像那样被丢弃,所以我的数据是一致的?
- 关于为什么我在部署到云时没有得到正确结果的任何其他想法?
解决方案
“有限”是什么意思?
这与“无限”相反。它将重试不超过设定的次数。
有什么办法可以控制这个数字?
除了修改SDK的源代码,没有。SDK 本身会公布一个特定的数字,因为它可能会发生变化。
我怎样才能确保我的交易在某个时候被执行并且不会像那样被丢弃,所以我的数据是一致的?
检测错误并在您的应用程序中重试。如果您没有看到交易因错误而失败,则说明没有任何问题。
关于为什么我在部署到云时没有得到正确结果的任何其他想法?
由于我们看不到您究竟在做什么来触发该功能,也没有具体的预期结果可以比较,所以真的不可能说。
推荐阅读
- discord - 检查消息是否有 7 个字母,然后发送到频道
- python - 使用 genfromtxt() 和转换器导入 csv
- c# - 没有按钮的弹出窗口 Xamarin.Forms
- c++ - Azure Function 项目在本地构建和部署,但不是来自 azure dev ops 管道
- c - 是否从 C 标准定义的同一联合中的不同成员分配给联合成员?
- python - 如何调整csv文件的大小
- google-bigquery - 为什么 Apache Beam BigQueryIO 每次运行都使用相同的 JobId?
- javascript - 在新选项卡中打开 Stripe 结帐,而不是重定向到结帐
- kotlin - Kotlin 支持 OptionSet 吗?
- linux - 如何在彼此下一个一个地grep相似的值?