Ненадежные транзакции Google Firebase - PullRequest
0 голосов
/ 16 марта 2020

В моей (очень упрощенной) модели у меня есть пользователи, account и 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. Есть еще какие-то идеи относительно того, почему я не получаю правильные результаты при развертывании в облаке?

1 Ответ

1 голос
/ 16 марта 2020

Что означает "конечный"?

Это противоположность "безлимитному". Он будет повторяться не более установленного числа раз.

Любой способ управления этим числом?

Кроме изменения исходного кода SDK, нет. Сам SDK объявляет определенный c номер, так как он может измениться.

Как я могу убедиться, что мои транзакции выполняются в какой-то момент и не сбрасываются таким образом, чтобы мои данные были согласованными ?

Обнаружить ошибку и повторить попытку в вашем приложении. Если вы не видите, что транзакция завершилась неудачно с ошибкой, то ничего не пошло не так.

Есть еще идеи, почему я не получаю правильные результаты при развертывании в облаке?

Поскольку мы не можем видеть, что именно вы делаете для запуска функции, и не имеем никаких конкретных c ожидаемых результатов для сравнения, на самом деле невозможно сказать.

...