下面的简单代码冻结了。
要进行复制,只需将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分钟。
答案 0 :(得分:2)
目前尚不清楚您要做什么,但是您至少有两个问题:
您不应该在事务内的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()
调用来做到这一点。这就是为什么要挂电话的原因。
在事务内部引发(未处理的)异常将进入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')
,但与您当前的问题无关。