为什么此Firestore交易冻结? [英] Why is this Firestore Transaction freezing?
问题描述
下面的简单代码冻结了.
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:
-
您不应该在事务内的
kittyRef
上直接调用set()
-您已通过在事务内读取对象来锁定了该对象.您需要通过transaction.set()
调用来做到这一点.这就是为什么要挂电话的原因.
You shouldn't be directly calling
set()
onkittyRef
inside the transaction -- you've locked the object by reading it inside that transaction. You need to do that with atransaction.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屋!