为什么此Firestore交易冻结? [英] Why is this Firestore Transaction freezing?

查看:42
本文介绍了为什么此Firestore交易冻结?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的简单代码冻结了.

The simple code below is freezing.

要复制,只需将 this.firestoreProvider 替换为 admin.initializeApp().firestore()

To reproduce, just replace this.firestoreProvider with admin.initializeApp().firestore()

   console.log('Init the cat')
        const kittyRef = this.firestoreProvider
            .fs
            .collection('cats')
            .doc('kitty')
        await kittyRef.set({
            name: 'Kitty',
            age: 85,
            feedCount: 0,
        })
        console.log('Feeding the cat')
        await this.firestoreProvider.fs.runTransaction(async transaction => {
            const snapshot = await transaction.get(kittyRef);
            const cat = snapshot.data()
            if(cat.isDead) return
            if(cat.age > 84) {
                cat.isDead = true
                await kittyRef.set(cat); // this need be written to the db
                throw new Error('Kitty is dead')
            }
            cat.feeCount ++
            await transaction.set(kittyRef, cat)
        }, {maxAttempts: 5})
        console.log('success')

我还发现,运行此代码后,它会冻结,但同时也会冻结所有尝试读取 kittyRef 大约1分钟的客户端.

I also discovered that once you run this code, it freezes but it also freezes every client that tries to read the kittyRef for about 1 minutes.

推荐答案

目前尚不清楚您要做什么,但是您至少有两个问题:

It is not entirely clear what you are trying to do, but you have at least 2 problems:

  1. 您不应该在事务内的 kittyRef 上直接调用 set() -您已通过在事务内读取对象来锁定了该对象.您需要通过 transaction.set()调用来做到这一点.这就是为什么要挂电话的原因.

  1. You shouldn't be directly calling set() on kittyRef inside the transaction -- you've locked the object by reading it inside that transaction. You need to do that with a transaction.set() call. This is why you are getting a hang.

在事务内部引发(未处理的)异常将导致导致其中止,因为它会导致 updateFunction 返回失败的承诺.此处有更多文档.最好的答案是从事务功能中传递信息并在交易结束后进行处理.

Throwing an (unhandled) exception inside the transaction is going to cause it to abort as it will cause the updateFunction to return a failed promise). More documentation here. The best answer here would be to pass information out of the transaction function and handle it once the transaction is over.

因此,此代码将运行并完成,并将猫标记为死亡,但不会引发错误.足以让您入门:

So, this code will run and complete and leave the cat marked as dead, but it won't throw the error. It should be enough to get you started though:

console.log('Init the cat')
const kittyRef = admin.firestore()
    .collection('cats')
    .doc('kitty')
await kittyRef.set({
      name: 'Kitty',
      age: 85,
      feedCount: 0,
})
console.log('Feeding the cat')
await admin.firestore().runTransaction(async transaction => {
      const snapshot = await transaction.get(kittyRef);
      const cat = snapshot.data()
      if(cat.isDead) return
      if(cat.age > 84) {
            cat.isDead = true
            await transaction.set(kittyRef, cat); // this need be written to the db
            console.log('kitty now dead');
            return;
      }
      cat.feeCount ++
      await transaction.set(kittyRef, cat)
}, {maxAttempts: 5})
console.log('success')

此外,我注意到您似乎输入了 feeCount 而不是 feedCount ,但这与您当前的问题无关.

Also, I note it appears you have a typo of feeCount instead of feedCount, but that is not related to your current question.

这篇关于为什么此Firestore交易冻结?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆