【问题标题】:How to stop firebase functions from propagating triggers如何阻止firebase函数传播触发器
【发布时间】:2022-02-09 23:49:27
【问题描述】:

我有一个 Firebase 函数,可以在删除评论时减少评论计数,就像这样

export const onArticleCommentDeleted = functions.firestore.document('articles/{articleId}/comments/{uid}').onDelete((snapshot, context) => {
    return db.collection('articles').doc(context.params.articleId).update({
        commentCount: admin.firestore.FieldValue.increment(-1)
    })
})

我还有 firebase 函数,可以在删除文章时递归删除文章的 cmets

export const onArticleDeleted = functions.firestore.document('articles/{id}').onDelete((snapshot, context) => {
    const commentsRef = db.collection('articles').doc(snapshot.id).collection('comments');
    db.recursiveDelete(commentsRef); // this triggers the onArticleCommentDeleted multiple times
})

当我删除一篇文章时,会触发 onArticleCommentDeleted 并尝试更新已删除的文章。当然,我可以在更新之前检查文章是否存在。但是真的很麻烦,也很浪费资源。

有什么方法可以避免进一步传播触发器?

【问题讨论】:

  • 另一种方法是将commentCount 存储在另一个名为article_aggregation 的具有相同ID 的集合中。因此,当一篇文章被删除时,onArticleCommentDeleted 会更新 article_aggregation 中的文档而不是文章集合。这样可以避免更新不存在的文章。但这会将垃圾文档留在 article_aggregation 中。当你加载一篇文章时,它需要额外阅读相应的 article_aggregation 以获得 commentCount。

标签: node.js google-cloud-firestore google-cloud-functions event-propagation


【解决方案1】:

我认为问题出在我使用触发器的方式上。通常,在子文档上实现 onDelete 触发器更新其父文档并不是一个好主意。这肯定会引起冲突。

相反,在客户端,我使用事务

...
runTransaction(async trans => {
    trans.delete(commentRef);
    trans.update(articleRef, {
        commentCount: admin.firestore.FieldValue.increment(-1)
    })
})

这可以确保如果其中一个操作失败,它们都会失败,并消除触发器。依赖客户端不是最好的主意,但我认为我们可以考虑权衡。

【讨论】:

    【解决方案2】:

    当您删除该文章的 cmets 时,无法阻止触发 cmets 上的云功能。正如您已经说过的,您必须在函数代码本身中检查该条件。

    【讨论】:

    • 如果我们有 100 个 cmets,我们必须检查该文章是否存在 100 次,尽管我们 100% 知道它不存在。这对我来说是不可接受的。我们还能做什么?
    猜你喜欢
    • 2020-04-18
    • 2012-08-06
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 2021-06-15
    • 2020-12-09
    • 1970-01-01
    相关资源
    最近更新 更多