Firebase云事务不总是完成

oknwwptz  于 2023-10-22  发布在  其他
关注(0)|答案(1)|浏览(142)

当一个新的review被发布到子集合reviews中时,我试图用一个事务来更新Firestore数据库中restaurant文档的平均评级。下面的代码适用于评论缓慢进入的情况,但如果我在几秒钟内插入10条评论进行压力测试,它将不再正确更新平均评级(即,它可能只计算前5个评论,而不会基于其余的评论进行更新)。我对事务的理解是,当数据在其脚下发生变化时,它会自动重新运行,以确保正确更新值。
这里是使用的云函数。

exports.reviewCreated = functions.firestore.document('/restaurants/{restaurantid}/reviews/{reviewid}').onCreate((snapshot, context) => {

    const rest_id = context.params.restaurantid;
    const rest_ref = admin.firestore().collection('restaurants').doc(rest_id)
    const rest_rating = snapshot.data().rest_rating;

    console.log('The new rest rating is: ' + rest_rating);
    try {
        admin.firestore().runTransaction((t) => {
            return t.get(rest_ref).then((rest_doc) => {
                const new_total_reviews = rest_doc.data().totalReviews + 1;
                const current_avg_rating = rest_doc.data().averageRating

                const new_avg_rating = current_avg_rating + ((rest_rating - current_avg_rating)/new_total_reviews);
                t.update(rest_ref, {totalReviews: new_total_reviews,
                                averageRating: new_avg_rating});
            });
        })

    } catch (e) {
        console.log('[Review Created] Transaction Failed', e);
        return null;
    }
});

为了测试这个。我在我的应用程序的调试屏幕上有一个按钮来插入一个假的评论,代码如下

<Button title = 'Add Review! (Test)' 
    onPress = {() => 
    {
        console.log(this.state.uid);
        var new_uuid = uuid.v4();

        firestore()
        .collection('restaurants')
        .doc(this.state.restid)
        .collection('reviews')
        .doc(new_uuid)
        .set({
            rest_rating: Math.floor(Math.random() * 5) + 1,
            review_name: 'test'
        });
    }}
/>

我是相当新的TS,并尽我最大的努力学习绳索,所以任何阅读/视频观看也将是有帮助的!:)

hmtdttj4

hmtdttj41#

您没有正确管理云函数的生命周期。正如doc中所解释的,您需要“通过返回一个JavaScript promise来解析执行异步处理的函数(也称为“后台函数”)”。
在你的例子中,你应该返回runTransaction()方法返回的Promise,如下所示:

exports.reviewCreated = functions.firestore.document('/restaurants/{restaurantid}/reviews/{reviewid}').onCreate((snapshot, context) => {

    const rest_id = context.params.restaurantid;
    const rest_ref = admin.firestore().collection('restaurants').doc(rest_id)
    const rest_rating = snapshot.data().rest_rating;

    console.log('The new rest rating is: ' + rest_rating);
    return admin.firestore().runTransaction((t) => {   // !!! See the return here
        return t.get(rest_ref).then((rest_doc) => {
            const new_total_reviews = rest_doc.data().totalReviews + 1;
            const current_avg_rating = rest_doc.data().averageRating

            const new_avg_rating = current_avg_rating + ((rest_rating - current_avg_rating) / new_total_reviews);
            t.update(rest_ref, {
                totalReviews: new_total_reviews,
                averageRating: new_avg_rating
            });
        });
    })
    .catch(e => {
        console.log('[Review Created] Transaction Failed', e);
        return null;
    });
});

通过不正确地管理云函数的生命周期,您可能会产生云函数的一些“不稳定”行为(如您所提到的“事务不总是完成”)。
在后台触发的云函数中返回Promise(或值)向云函数平台指示它不应该终止函数,直到Promise已经实现并且避免在异步操作完成之前终止它。
因此,“事务并不总是完成”的原因很可能如下:有时您的云函数会在异步事务完成之前终止,原因如上所述。并且其他时间,云函数平台不立即终止函数,并且异步事务可以完成(即,有可能在云功能终止之前完成)。

相关问题