如何在Cloud Functions中进行幂等聚合? [英] How to make idempotent aggregation in Cloud Functions?

查看:80
本文介绍了如何在Cloud Functions中进行幂等聚合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Firebase Cloud Function,该功能可更新有关数据库中某些文档的某些汇总信息.这是一个非常简单的功能,只需将1加到文档总数中即可.类似于在Firestore文档中找到的示例函数.

I'm working on a Firebase Cloud Function that updates some aggregate information on some documents in my DB. It's a very simple function and is simply adding 1 to a total # of documents count. Much like the example function found in the Firestore documentation.

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

I just noticed that when creating a single new document, the function was invoked twice. See below screenshot and note the logged document ID (iDup09btyVNr5fHl6vif) is repeated twice:

经过一番挖掘,我发现了这样的帖子表示以下内容:

After a bit of digging around I found this SO post that says the following:

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

Delivery of function invocations is not currently guaranteed. As the Cloud Firestore and Cloud Functions integration improves, we plan to guarantee "at least once" delivery. However, this may not always be the case during beta. This may also result in multiple invocations for a single event, so for the highest quality functions ensure that the functions are written to be idempotent.

(从Firestore文档中:限制和保证)

(From Firestore documentation: Limitations and guarantees)

这导致我的文档出现问题.上面提到的云函数是幂等的(换句话说,无论函数运行一次还是运行多次,它们更改的数据都应该相同).但是,我以前链接(在我看来)的示例函数不是幂等:

Which leads me to a problem with their documentation. Cloud Functions as mentioned above are meant to be idempotent (In other words, data they alter should be the same whether the function runs once or runs multiple times). However the example function I linked to earlier (to my eyes) is not idempotent:

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

如果该函数运行一次,则将增加总数据,就像添加了一个等级,但是如果该功能再次以相同的等级运行,则将增加总数据,就像添加了两个等级一样.

If the function runs once, the aggregate data is increased as if one rating is added, but if it runs again on the same rating it will increase the aggregate data as if there were two ratings added.

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

Unless I'm misunderstanding the concept of idempotence, this seems to be a problem.

是否有人对如何通过幂等方式通过Cloud Functions增加/减少Cloud Firestore中的聚合数据有任何想法?

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

(And of course doesn't involve querying every single document the aggregate data is regarding)

加分点:有人知道Cloud Firestore脱离beta版后,功能是否仍然需要幂等吗?

推荐答案

Cloud Functions文档提供了有关如何

The Cloud Functions documentation gives some guidance on how to make retryable background functions idempotent. The bullet point you're most likely to be interested in here is:

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

Impose a transactional check outside the function, independent of the code. For example, persist state somewhere recording that a given event ID has already been processed.

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

The event parameter passed to your function has an eventId property on it that is unique, but will be the same when an even it retried. You should use this value to determine if an action taken by an event has already occurred, so you know to skip the action the second time, if necessary.

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

As for how exactly to check if an event ID has already been processed by your function, there's a lot of ways to do it, and that's up to you.

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

You can always opt out of making your function idempotent if you think it's simply not worthwhile, or it's OK to possibly have incorrect counts in some (probably rare) cases.

这篇关于如何在Cloud Functions中进行幂等聚合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆