Firebase函数在Function.MapValues

时间:2018-05-18 12:15:05

标签: node.js typescript firebase firebase-realtime-database google-cloud-functions

我遇到了一个firebase函数的问题,用TypeScript编写的Node.js环境。我有一个https-endpoint功能,客户端可以发送需要存储在数据库中的数据。为了知道哪些对象已经添加到数据库,它首先读取一个路径(“lookup”),该路径具有对象的简化注册表(lookup/:objectId/true)。然后它生成应在实际对象路径上更新的值,并在数据库中更新这些值。

功能如下:

export const scrapeAssignments = functions.https.onCall((data, context) => {
    const htmlString = data.htmlString
    // const htmlString = fs.readFileSync(testPath.join(__dirname, "./assignmentListExample.html"), { encoding: 'utf8' })
    if (!(typeof htmlString === 'string') || htmlString.length === 0) {
        throw new functions.https.HttpsError('invalid-argument', 'The function must be called with one argument "htmlString"');
    }

    const userId = getUserIdFromCallableContext(context)
    console.log("userId", userId)
    let newAssignments: ScrapedAssignment[] = []
    try {
        newAssignments = parseAssignment(htmlString)
    } catch (e) {
        const error = <Error>e
        throw new functions.https.HttpsError('not-found', 'parsing error: ' + error.message)
    }

    return admin.database().ref("lookup").child(userId).child("assignments")
        .once("value", lookupSnapshot => {
            const oldAssignmentsLookup = lookupSnapshot.val() || {}
            const newAssignmentsLookup = makeLookup(newAssignments)

            // 1. Create update values for scraped assignment data
            let scrapedAssignmentUpdateValues = newAssignments.reduce((prev, current) => {
                const prefixed = prefixObject(current.id + "/", current)
                return { ...prev, ...prefixed }
            }, {})

            // 2. Use the diff from the two lookups to find old assignments to delete
            const removeAssignmentsValues = {}
            Object.keys(oldAssignmentsLookup).forEach(assignmentId => {
                if (isUndefined(newAssignmentsLookup[assignmentId]))
                    removeAssignmentsValues[assignmentId] = null
            })

            // 3. Add other user values to newly found assignments
            Object.keys(newAssignmentsLookup).forEach(assignmentId => {
                if (isUndefined(oldAssignmentsLookup[assignmentId])) {
                    const doneKey = assignmentId + "/done" 
                    scrapedAssignmentUpdateValues[doneKey] = false
                }
            })

            const combinedValues = { ...scrapedAssignmentUpdateValues, ...removeAssignmentsValues }
            return admin.database().ref("userAssignments").child(userId).update(combinedValues)
        }).catch(reason => {
            throw new functions.https.HttpsError('internal', 'Database reason: ' + reason)
        })
})

我看到数据被写入正确的位置,一切似乎按预期进行,除了当我从iOS应用程序调用该函数时,它返回“Internal” -error < / p>

当我在云控制台中检查功能日志时,我看到以下错误:

  

assignment-scrapeAssignments uolk47opctna未处理的错误RangeError:   Function.mapValues超出了最大调用堆栈大小   (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13395:23)   在编码   (/user_code/node_modules/firebase-functions/lib/providers/https.js:204:18)   在   /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13400:38   在   /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4925:15   在baseForOwn   (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:3010:24)   在Function.mapValues   (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13399:7)   在编码   (/user_code/node_modules/firebase-functions/lib/providers/https.js:204:18)   在   /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13400:38   在   /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4925:15   在baseForOwn   (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:3010:24)   在Function.mapValues   (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13399:7)

我只能读出来的是,它是“RangeError:超出最大调用堆栈大小” - 错误,并且Function.mapValues发生了一些事情。正如我可以从this SO question读到的那样,同时读取和写入同一位置似乎是一个问题。但是我很确定我在这里没有这样做。除了实际的错误外,一切看起来都应该是这样的。

当更新combinedValues时,它是一个具有~300个键/值对的对象,这是一个问题吗?

1 个答案:

答案 0 :(得分:0)

就像您的函数用完了内存一样,每个云函数都为其执行分配了内存。 您可以尝试通过以下步骤将堆栈大小从其默认值(256MB)增加到2GB: 单击功能->仪表板,然后转到有问题的功能,然后单击右侧菜单“详细的使用情况统计信息”:

enter image description here

然后在Google云信息中心的功能详细信息上,点击“修改”:

enter image description here 然后将“分配的内存”的值增加到2GB(或降低足够的值):

enter image description here

注意:您应该记住,当您的数据增长时,您可能会超过最高限制,因此在云功能中进行查询时应考虑到这一点