![](/img/trans.png)
[英]Cloud Firestore emulator not running when testing Cloud Functions locally
[英]Firestore transactions showing unexpected behaviour when used in cloud functions
我正在编写一个应用程序,其中包含用户可以预订产品的库存。 我想确保两个用户不能同时预订一个产品,为此,我打算使用交易。 使用 Firebase SDK 中的事务时,一切都按预期工作,但在使用可调用云 function 中的事务时出现意外行为。 为了模拟两个用户碰巧预订相同产品的用例,我在我的云 function 中使用 setTimeout 将 function 暂停 3 秒。 我正在从具有不同用户上下文的 2 个不同客户端启动此 function。
export const reserveProduct = functions.https.onCall(async (data,context) => {
function testTimeout(){
return new Promise((resolve,reject) => {
setTimeout(()=> {
return resolve(true)
},3000)
})
}
if(!context.auth){
return {
error: `You must be logged in to reserve products`
}
}else{
const productRef = admin.firestore().collection('products').doc(data.productID)
const userRef = admin.firestore().collection('users').doc(context.auth.uid)
return admin.firestore().runTransaction((transaction) => {
return transaction.get(productRef).then(async(doc) => {
if(doc.get('status') == 'reserved'){
throw "Document already reserved!"
}else{
console.log("Product not reserved, reserving now!")
}
await testTimeout()
transaction.update(productRef, {status: 'reserved'});
transaction.update(userRef, {reserved: admin.firestore.FieldValue.arrayUnion(data.productID)})
})
}).then(() => {
console.log("Transaction Successfully committed !")
}).catch((error) => {
throw "Transaction failed, product already reserved"
})
}
在同时从 2 个不同的客户端运行此 function 调用后,来自我的第一个客户端的 function 调用按预期成功返回,但仅在大约 35 秒后才返回(这对于事务的简单性来说太长了)。 但是,第二个 function 调用超时,没有返回任何值。 我没有看到任何文档明确说明在可调用的云函数中使用事务,在模拟器中使用它也不应该受到影响。
我期望简单地获得任何 function 调用能够首先修改数据的返回值,并从 function 中捕获错误,该 function 已重试并验证了保留的 Z9ED39E2EA931586B576A985A694E
任何帮助将不胜感激,谢谢!
这两个地方之间的一个主要区别在于 SDK 处理交易的方式:
客户端 SDK 对事务使用乐观的比较和设置方法,这意味着它们将您在事务中读取的值与您正在写入的数据一起传递。 然后,如果您读取的文档尚未更新,服务器只会写入新数据。
服务器端 SDK(在您的 Cloud Function 中使用)对事务使用更传统的悲观方法,并对您在事务中读取的每个文档进行锁定。
您可以在文档中的 SDK 中阅读有关数据库争用的更多信息。
虽然我不确定这会如何影响您的代码,但我怀疑这与您在客户端和服务器端实现之间看到的行为差异有关。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.