首页 > 解决方案 > 不可靠的 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)说:

“事务读取了在事务之外修改的文档。在这种情况下,事务会自动再次运行。事务会重试有限次。”

所以我的问题:

  1. “有限”是什么意思?
  2. 有什么办法可以控制这个数字?
  3. 我怎样才能确保我的交易在某个时候被执行并且不会像那样被丢弃,所以我的数据是一致的?
  4. 关于为什么我在部署到云时没有得到正确结果的任何其他想法?

标签: arraysfirebasegoogle-cloud-firestoretransactionsgoogle-cloud-functions

解决方案


“有限”是什么意思?

这与“无限”相反。它将重试不超过设定的次数。

有什么办法可以控制这个数字?

除了修改SDK的源代码,没有。SDK 本身会公布一个特定的数字,因为它可能会发生变化。

我怎样才能确保我的交易在某个时候被执行并且不会像那样被丢弃,所以我的数据是一致的?

检测错误并在您的应用程序中重试。如果您没有看到交易因错误而失败,则说明没有任何问题。

关于为什么我在部署到云时没有得到正确结果的任何其他想法?

由于我们看不到您究竟在做什么来触发该功能,也没有具体的预期结果可以比较,所以真的不可能说。


推荐阅读