为什么此Firestore交易冻结?

时间:2020-08-04 12:36:40

标签: node.js firebase google-cloud-firestore

下面的简单代码冻结了。

要进行复制,只需将this.firestoreProvider替换为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分钟。

1 个答案:

答案 0 :(得分:2)

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

  1. 您不应该在事务内的CString RITexts::GetText(long Number, long LangID) { CString result; static BYTE parms[] = VTS_I4 VTS_I4; InvokeHelper(0x5, DISPATCH_METHOD, VT_BSTR, (void*)&result, parms, Number, LangID); return result; } 上直接调用OLEAUT32.dll!SysReAllocStringLen 76543120 mfc140ud.dll!ATL::ChTraitsCRT<wchar_t>::ReAllocSysString Line 815 + 0xe bytes 7a2d0012 mfc140ud.dll!ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >::SetSysString Line 2288 + 0x16 bytes 7a2d0a39 (-> ComClass) LangSupp.dll!CTexts::GetText Line 343 + 0x9 bytes 7b1698b2 OLEAUT32.dll!DispCallFunc + 0x16d bytes 7655840d OLEAUT32.dll!CTypeInfo2::Invoke + 0x2e6 bytes 7653aca6 LangSupp.dll!ATL::CComTypeInfoHolder::Invoke Line 4204 + 0x31 bytes 7b15c056 LangSupp.dll!ATL::IDispatchImpl<ITexts,&IID_ITexts,&LIBID_LANGSUPPLib,1,0,ATL::CComTypeInfoHolder>::Invoke Line 5163 + 0x2a bytes 7b15bfa2 mfc140ud.dll!COleDispatchDriver::InvokeHelperV Line 399 + 0x7 bytes 7a1e6d6b mfc140ud.dll!COleDispatchDriver::InvokeHelper Line 554 + 0x1d bytes 7a1e6597 (-> Client) Managers.dll!RITexts::GetText Line 104 + 0x1b bytes 7ac2ce3a ,而是通过在事务内读取对象来锁定该对象。您需要通过set()调用来做到这一点。这就是为什么要挂电话的原因。

  2. 在事务内部引发(未处理的)异常将进入cause it to abort,因为它将导致kittyRef返回失败的诺言)。 More documentation here。最好的答案是pass information out of the transaction function,并在交易结束后进行处理。

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

transaction.set()

此外,我注意到您似乎输入了updateFunction而不是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') ,但与您当前的问题无关。