【问题标题】:Cloud function is timing out as there are too many documents to update云功能超时,因为要更新的文档太多
【发布时间】:2021-06-02 13:44:04
【问题描述】:

我有一个每天作为 cron 作业运行的云功能,它为我们的每个用户创建一个每日统计文档。现在的问题是,随着我们拥有的用户数量,该功能正在超时,因此无法为我们的每个用户创建所需的文档。

功能很简单:

    export const createDailyStatsDocument = runWith({timeoutSeconds: 540}).https.onRequest((req, res) => {
    corsHandler(req, res, async () => {
        try {
            const users = await db.collection('users').get();
            for (const userDoc of users.docs) {
                 const data = {
                    uid: userDoc.uid,
                    test: 'test'
                }
                const statsRef = await createStatsDoc(data)
            }
            return res.status(200).send({message: 'Successfully created all users documents'});
        } catch (e) {
            console.log({e});
            return _handleError(res, e.status, e.message);
        }
    })
});

我已将函数超时增加到 Firestore 允许的最大值,但仍然遇到同样的问题。有没有人解决如何增加这些函数的超时时间,或者以某种方式为在单独实例中运行的每个循环迭代触发另一个函数,因此不影响这个超时时间?

【问题讨论】:

    标签: javascript node.js http google-cloud-firestore google-cloud-functions


    【解决方案1】:

    下面的代码应该可以解决问题。在 HTTPS 云函数中,所有工作都委托给 PubSub 云函数(为每个用户发布一条 PubSub 消息)。完成后,可以通过发送响应来完成 HHTPS Cloud Function。

    const functions = require('firebase-functions');
    const admin = require('firebase-admin');
    
    const { PubSub } = require('@google-cloud/pubsub');  // <== See here!!
    const pubSubClient = new PubSub();
    
    admin.initializeApp();
    
    // A function that will publish a Pub/Sub message
    async function publishMessage(messageConfig) {
        try {
    
            const topicName = messageConfig.topicName;
            const pubSubPayload = messageConfig.pubSubPayload;
    
            let dataBuffer = Buffer.from(JSON.stringify(pubSubPayload));
            await pubSubClient.topic(topicName).publish(dataBuffer);
    
        } catch (error) {
            throw error;
        }
    }
    
    // Your adapted Cloud Function
    export const createDailyStatsDocument = runWith({ timeoutSeconds: 540 }).https.onRequest((req, res) => {
        corsHandler(req, res, async () => {
            try {
                const users = await db.collection('users').get();
                for (const userDoc of users.docs) {
    
                    const messageConfig = {
                        topicName: 'daily-stats',
                        pubSubPayload: {
                            uid: userDoc.uid,
                            test: 'test'
                        }
                    }
                    await publishMessage(messageConfig);
                }
                return res.status(200).send({ message: 'Successfully created all PUBSub Messages' });
            } catch (e) {
                console.log({ e });
                return _handleError(res, e.status, e.message);
            }
        })
    });
    
    
    // The Pub/Sub Cloud Function that calculates the stat for each user
    exports.calculateDailyStat = functions.pubsub.topic('daily-stats').onPublish(async (message) => {
    
        try {
    
            const data = {
                uid: message.json.uid,
                test: message.json.test
            }
            await createStatsDoc(data)
    
            return null;
    
        } catch (error) {
            console.error(error);
            return null;
        }
    
    });
    

    请注意,此代码为 每个 用户创建 Pub/Sub 消息,因此会为每个用户触发 Pub/Sub Cloud Function。如果您想批量对用户进行分组,则由您来调整它。只需修改 pubSubPayload 以传递数据数组,并在 Pub/Sub Cloud Function 循环中遍历此数组。

    【讨论】:

      【解决方案2】:

      没有办法延长云函数运行超过其最大值的时间。

      您遇到的问题的典型解决方案是将工作分成更小的块,并让它们作为单独的任务运行。例如,如果您创建最多 500 个 UID 的块,然后将它们发布到 PubSub 主题,您可以在该主题上触发另一个 Cloud Function,并在一次批量写入中创建这些统计文档。

      【讨论】:

      • 我可以在不超时的情况下异步地为这个函数中的每个块发布到 pubsub 主题吗?
      • 是的,确实是这样。您的父函数将在完成读取和创建块后立即完成,而每个块然后在其自己的 Cloud Function 调用中运行。
      • 这看起来怎么样?是否不需要在每个函数调用上等待,因此只有结束的函数都已完成?
      • 不,这不太可能有多大帮助。如果您想要所有这些的完成机制,则必须在顶部实现它。就像让原始函数写入要完成的任务总数,然后让每个 PubSub 处理程序增加一个其完成工作的计数器。客户可以同时收听并检查completedCount == userCount
      • 你能举个例子吗?不要以为我很明白你的意思
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-27
      • 2019-08-07
      • 1970-01-01
      • 2018-12-15
      • 2020-12-24
      • 2020-02-01
      • 2018-05-17
      相关资源
      最近更新 更多