【问题标题】:Firestore trigger timeouts occasionallyFirestore 偶尔会触发超时
【发布时间】:2018-12-11 19:34:46
【问题描述】:

我有一个Cloud Firestore trigger,负责在我的应用中调整用户钱包的余额。

exports.onCreateTransaction = functions.firestore
    .document('accounts/{accountId}/transactions/{transactionId}')
    .onCreate(async (snap, context) => {
        const { accountId, transactionId  } = context.params;

        const transaction = snap.data();

        // See the implementation of alreadyTriggered in the next code block
        const alreadyTriggered = await firestoreHelpers.triggers.alreadyTriggered(context);

        if (alreadyTriggered) {
            return null;
        }

        if (transaction.status === 'confirmed') {
            const accountRef = firestore
                .collection('accounts')
                .doc(accountId);

            const account = (await accountRef.get()).data();
            const balance = transaction.type === 'deposit' ? 
                    account.balance + transaction.amount : 
                    account.balance - transaction.amount;

            await accountRef.update({ balance });
        }

        return snap.ref.update({ id: transactionId });
    });

作为触发器实际上可能是be called more than once,我添加了这个alreadyTriggered 辅助函数:

const alreadyTriggered = (event) => {
    return firestore.runTransaction(async transaction => {
        const { eventId } = event;
        const metaEventRef = firestore.doc(`metaEvents/${eventId}`);
        const metaEvent = await transaction.get(metaEventRef);

        if (metaEvent.exists) {
            console.error(`Already triggered function for event: ${eventId}`);
            return true;
        } else {
            await transaction.set(metaEventRef, event);
            return false;
        }
    })
};

大多数情况下,一切都按预期进行。但是,今天我收到一个超时错误,导致数据库中的数据不一致。

函数执行耗时 60005 毫秒,完成状态为:'timeout'

这个超时的原因是什么?以及如何确保它不再发生,以便我的交易金额成功反映在账户余额中?

【问题讨论】:

    标签: node.js firebase google-cloud-firestore google-cloud-functions


    【解决方案1】:

    如上所述,关于多次执行的声明是一个测试版限制。 Cloud Functions 现已完成测试。当前保证是at-least-once默认执行。如果您在云控制台中enable retries,您只会收到多个可能的事件。如果您想确保可靠地处理您的事件,您应该这样做。

    超时的原因可能永远无法确定。可能有很多原因。也许网络中出现了故障,或者系统某处出现了短暂的停机时间。重试应该通过多次传递事件来帮助您从这些临时情况中恢复,因此您的函数可以成功。

    【讨论】:

    • 感谢您的回答!即使已经成功调用,触发器似乎也被多次调用。此外,有时会在第一个电话返回之前拨打第二个电话。
    • 我特别指的是使用相同事件 ID 调用触发器的情况。问题是:如果启用了“失败重试”,事件 ID 会与第一个不同吗?
    • 我认为你必须更具体地了解你是如何观察这种行为的。
    • 好的,我试试。在下面的屏幕截图中,您可以看到这个触发器被多次调用,具有相同的事件 ID:imgur.com/a/D1ubYQy
    • 虽然更重要的是:imgur.com/a/mgtXWx1 从屏幕截图中可以看出,c1 是成功运行的触发器的第一个调用。但是,还有 2 次对触发器的调用,标记为 c2 和 c3,它们紧随其后被调用。而且,c3 似乎在 c2 完成之前就已经开始了。为了向您展示 c2 和 c3 确实是针对与 c1 相同的事件触发的,我在 c1(d1 和 d2)及其事件 id - d3 中的参数下划线。可以看到c2和c3中被调用的事件的id与文档中的参数匹配。
    猜你喜欢
    • 2021-12-26
    • 1970-01-01
    • 2019-01-24
    • 2014-03-23
    • 2018-03-03
    • 1970-01-01
    • 2015-08-10
    • 2013-09-20
    • 1970-01-01
    相关资源
    最近更新 更多