Firebase 云交易并不总是完成

Firebase cloud transactions not always finishing

当新的 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 还很陌生,我正在尽我最大的努力学习技巧,所以任何 readings/videos 观看也会有所帮助! :)

您没有正确管理 Cloud Functions 的生命周期。如 doc 中所述,您需要通过 return 一个 JavaScript promise 来“解析执行异步处理的函数(也称为“后台函数”)”。

在您的情况下,您应该 return Promise return 通过 runTransaction() 方法编辑,如下所示:

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;
    });
});

如果不正确地管理 Cloud Function 的生命周期,您可能会产生一些 Cloud Function 的“不稳定”行为(如您所说,“交易并不总是完成”)。

在后台触发的 Cloud Function 中返回 Promise(或值)向 Cloud Function 平台表明它不应终止 Function,直到 Promise 已实现并避免它在异步操作完成之前终止。

所以“事务并不总是完成”的原因很可能如下:有时您的 Cloud Function 在异步事务完成之前终止,原因上面解释了。而其他时候,Cloud Function平台不会立即终止Function,异步事务可以完成(即有可能在Cloud Function终止之前完成)。