如何在云函数中进行幂等聚合?

sar*_*den 8 firebase google-cloud-functions google-cloud-firestore

我正在开发一个Firebase云功能,可以更新我的数据库中某些文档的一些聚合信息.这是一个非常简单的功能,只需将1个文档计数加1即可.与Firestore文档中示例函数非常相似.

我刚刚注意到,在创建单个新文档时,该函数被调用了两次.请参见下面的屏幕截图,并注意记录的文档ID(iDup09btyVNr5fHl6vif)重复两次:

在此输入图像描述

经过一番挖掘,我发现这个SO帖子说的如下:

目前不保证传递函数调用.随着Cloud Firestore和Cloud Functions集成的改进,我们计划保证"至少一次"交付.但是,在测试期间可能并非总是如此.这也可能导致单个事件的多次调用,因此对于最高质量的函数,确保函数被写为幂等的.

(来自Firestore文档:限制和保证)

这导致我的文档出现问题.如上所述的云函数意味着是幂等的(换句话说,无论函数运行一次还是多次运行,它们改变的数据应该相同).然而,我之前链接的示例函数(对我来说)并不是幂等的:

exports.aggregateRatings = firestore
  .document('restaurants/{restId}/ratings/{ratingId}')
  .onWrite(event => {
    // Get value of the newly added rating
    var ratingVal = event.data.get('rating');

    // Get a reference to the restaurant
    var restRef = db.collection('restaurants').document(event.params.restId);

    // Update aggregations in a transaction
    return db.transaction(transaction => {
      return transaction.get(restRef).then(restDoc => {
        // Compute new number of ratings
        var newNumRatings = restDoc.data('numRatings') + 1;

        // Compute new average rating
        var oldRatingTotal = restDoc.data('avgRating') * restDoc.data('numRatings');
        var newAvgRating = (oldRatingTotal + ratingVal) / newNumRatings;

        // Update restaurant info
        return transaction.update(restRef, {
          avgRating: newAvgRating,
          numRatings: newNumRatings
        });
      });
    });
});
Run Code Online (Sandbox Code Playgroud)

如果函数运行一次,则聚合数据会增加,就像添加一个评级一样,但如果它在相同的评级上再次运行,则会增加聚合数据,就像添加了两个评级一样.

除非我误解了幂等的概念,否则这似乎是一个问题.

有没有人对如何通过云功能以幂等方式增加/减少Cloud Firestore中的聚合数据有任何想法?

(当然不涉及查询汇总数据的每个文档)

加分:在Cloud Firestore出现测试版之后,是否有人知道功能是否仍需要幂等?

Dou*_*son 5

Cloud Functions文档为如何使可重试的后台函数幂​​等提供了一些指导。您最可能对此感兴趣的要点是:

在函数外部施加事务检查,与代码无关。例如,某处的持久状态记录了给定事件ID已被处理。

event传递给您的函数的参数具有唯一的eventId属性,但即使重试该参数也将相同。您应该使用此值来确定是否已发生由事件执行的操作,因此,您知道必要时第二次跳过该操作。

至于如何准确地检查事件ID是否已由您的函数处理,有很多方法可以执行,这取决于您。

如果您认为函数根本不值得,或者在某些(可能很少)的情况下可以计数不正确,您总是可以选择不让函数成为幂等。

  • 这应该添加到文档中,在该文档中您将显示非幂等聚合函数的示例(很多人可能不知道它有此缺陷而在后面跟随它)https://firebase.google.com/docs/firestore/solutions/aggregation# solution_cloud_functions (2认同)