繁体   English   中英

Firestore 事务在云功能中使用时表现出意外行为

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM