Firebase云事务不总是完成

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

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

  1. exports.reviewCreated = functions.firestore.document('/restaurants/{restaurantid}/reviews/{reviewid}').onCreate((snapshot, context) => {
  2. const rest_id = context.params.restaurantid;
  3. const rest_ref = admin.firestore().collection('restaurants').doc(rest_id)
  4. const rest_rating = snapshot.data().rest_rating;
  5. console.log('The new rest rating is: ' + rest_rating);
  6. try {
  7. admin.firestore().runTransaction((t) => {
  8. return t.get(rest_ref).then((rest_doc) => {
  9. const new_total_reviews = rest_doc.data().totalReviews + 1;
  10. const current_avg_rating = rest_doc.data().averageRating
  11. const new_avg_rating = current_avg_rating + ((rest_rating - current_avg_rating)/new_total_reviews);
  12. t.update(rest_ref, {totalReviews: new_total_reviews,
  13. averageRating: new_avg_rating});
  14. });
  15. })
  16. } catch (e) {
  17. console.log('[Review Created] Transaction Failed', e);
  18. return null;
  19. }
  20. });

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

  1. <Button title = 'Add Review! (Test)'
  2. onPress = {() =>
  3. {
  4. console.log(this.state.uid);
  5. var new_uuid = uuid.v4();
  6. firestore()
  7. .collection('restaurants')
  8. .doc(this.state.restid)
  9. .collection('reviews')
  10. .doc(new_uuid)
  11. .set({
  12. rest_rating: Math.floor(Math.random() * 5) + 1,
  13. review_name: 'test'
  14. });
  15. }}
  16. />

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

hmtdttj4

hmtdttj41#

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

  1. exports.reviewCreated = functions.firestore.document('/restaurants/{restaurantid}/reviews/{reviewid}').onCreate((snapshot, context) => {
  2. const rest_id = context.params.restaurantid;
  3. const rest_ref = admin.firestore().collection('restaurants').doc(rest_id)
  4. const rest_rating = snapshot.data().rest_rating;
  5. console.log('The new rest rating is: ' + rest_rating);
  6. return admin.firestore().runTransaction((t) => { // !!! See the return here
  7. return t.get(rest_ref).then((rest_doc) => {
  8. const new_total_reviews = rest_doc.data().totalReviews + 1;
  9. const current_avg_rating = rest_doc.data().averageRating
  10. const new_avg_rating = current_avg_rating + ((rest_rating - current_avg_rating) / new_total_reviews);
  11. t.update(rest_ref, {
  12. totalReviews: new_total_reviews,
  13. averageRating: new_avg_rating
  14. });
  15. });
  16. })
  17. .catch(e => {
  18. console.log('[Review Created] Transaction Failed', e);
  19. return null;
  20. });
  21. });

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

展开查看全部

相关问题