Как предотвратить конфликт записи транзакции и асинхронный запуск транзакции? - PullRequest
0 голосов
/ 17 апреля 2019

Итак, я сейчас запускаю несколько сценариев для сброса баланса пользователей в одном из наших приложений. Я использую Firestore, чтобы получить все задачи, а затем подсчитываю балансы, основанные на них для каждого из наших пользователей. Звучит просто, правда? Так должно быть, а его нет. Проблема в том, что транзакции прерываются из-за конфликтов записи в один и тот же документ. Это происходит потому, что все задачи передаются транзакции одновременно.

Я пытался использовать метод forEach, который вызывает их прерывание, потому что он пытается каждый раз обновлять одну и ту же запись пользователя. И я попытался (пусть задача задач), который дает мне ошибку «не может выполнить задачи».

async function updatestuff(){
  console.log("start");
  const tasksRef = db.collection('tasks');
  try {
          const allTasksSnapShot = await tasksRef.get();
          allTasksSnapShot.forEach(async(doc) => {
            //Run transaction for calculations for each task here
            const tskUser = doc.data().taskUser;
            const tuser = db.collection('backupusers').doc(tskUser);
                if(doc.data().taskStatus == 'Not Completed'){
                  console.log('NOT');}
                if(doc.data().taskStatus != 'Not Completed'){
                  console.log('Run transaction here and wait for it to finish?');
                  await db.runTransaction(async t => {
                  const userSnapShot =  await t.get(tuser);
                          if (!userSnapShot) {return console.log('not a thing')}
                          //get new balance calculated
                          const newBalance = userSnapShot.actualbalance + doc.data().taskBalanceAdj;
                          await t.update(tuser, {actualbalance: newBalance});
                  })
            }});
          console.log("end")
  }
  catch (err) {
    console.log('Error getting documents', err);
  }
}

В настоящее время конфликты между записями документов приводят к тому, что транзакции прерываются на полпути.

Я был бы очень признателен, если бы кто-нибудь помог мне в возможности передать каждую задачу в транзакцию асинхронным образом, ожидая завершения транзакции, а затем пропустив следующую задачу. Или другой способ, который даст те же результаты ....

Заранее спасибо, добрая добрая добрая (ые) душа (и)!

1 Ответ

0 голосов
/ 18 апреля 2019

Ваша updatestuff функция запускает столько асинхронных элементов работы, но не возвращает обещание, которое становится решающим, когда все они выполнены. Вы бы использовали это обещание в своей основной триггерной функции, чтобы облачные функции знали, что вся работа завершена, и все можно безопасно очистить. Если вы этого не сделаете, ваша функция может быть закрыта до завершения работы.

Имейте в виду, что использование async / await с forEach не очень хорошая идея. Функция forEach не будет ждать завершения асинхронной работы, прежде чем перейти к следующему элементу. Это закончится большим количеством транзакций в полете, и нет никакого способа узнать, когда они все завершены. Вместо этого вы можете не хотеть использовать async / await и вместо этого поместить все обещания транзакций в массив, а затем использовать Promise.all () для этого массива, чтобы создать новое обещание, которое разрешается, когда вся работа завершено. Верните это из своей функции, затем используйте это в своей основной триггерной функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...