【问题标题】:How to prevent Transaction write conflict and runTransaction asynchronously?如何防止事务写入冲突和异步运行事务?
【发布时间】:2019-04-17 20:01:08
【问题描述】:

因此,我目前正在运行一些脚本来重置我们其中一款应用中的用户余额。我正在使用 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);
  }
}

目前文档写入之间的冲突导致事务中途中止。

如果有人可以帮助我以异步方式将每个任务传递给事务,我将非常感激,等待事务完成然后传递下一个任务。 或者另一种可以获得相同结果的方法....

提前感谢你善良善良的灵魂!

【问题讨论】:

  • 您将 async/await 与 then() 和 catch() 结合使用。这使得你很难推断你的代码在做什么,甚至可能是不正确的。如果您想使用 async/await,为什么不在整个代码中应用它以保持一致性和可读性?
  • 你好,Doug,信不信由你,我已经看了你很久了,你的 Firecast 很棒!我更新了我的代码以删除 then catch 但是这让我意识到我可能需要重新访问这些视频和其他一些关于异步等待的示例。
  • 那么这里的错误到底是什么?
  • 所以当我运行它时,我得到“UnhandledPromiseRejectionWarning:错误:10 ABORTED:引用的事务已过期或不再有效。”大约一分钟后,功能停止。许多事务在前 30 秒内顺利完成。最后我得到一个错误,这些记录有太多争用,请再试一次,函数中止。所以我认为问题是由于任务被同步传递给事务,并且多次写入同一个文档,事务被中止。

标签: javascript transactions async-await google-cloud-firestore


【解决方案1】:

您的updatestuff 函数正在启动尽可能多的异步工作项,但它没有返回一个承诺,当所有这些工作都完成时,该承诺将成为解决方案。您将在主触发器函数中使用该承诺,让 Cloud Functions 知道所有工作都已完成,并且可以安全地清理所有内容。如果您不这样做,那么您的功能可能会在工作完成之前被关闭。

请记住,将 async/await 与 forEach 一起使用并不是一个好主意。 forEach 函数不会等到异步工作完成后再继续下一项。它将以大量交易在飞行中完成,并且无法知道它们何时全部完成。相反,您可能想要使用 async/await,而是将所有事务承诺推送到一个数组中,然后在该数组上使用 Promise.all() 创建一个新的承诺,当所有工作完成。从你的函数中返回它,然后在你的主触发器函数中使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多