Функции Firebase возвращают RangeError в Function.MapValues - PullRequest
0 голосов
/ 18 мая 2018

Я столкнулся с проблемой с функцией firebase, написанной на TypeScript для среды Node.js.У меня есть функция с https-конечной точкой, где клиент может отправлять данные, которые необходимо сохранить в базе данных.Чтобы узнать, какие объекты уже были добавлены в базу данных, он сначала считывает путь ( "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, она возвращает «Внутренний» -error

Когда я проверяю, что функция входит в системуВ облачной консоли я вижу следующую ошибку:

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 /провайдеры / 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.js49: 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:7)

Все, что я могу из этого прочитать, это то, что это "RangeError: Максимальный размер стека вызовов превышен" -ошибка, и что-то происходит в Function.mapValues.Как я могу прочитать из этого SO вопроса , похоже, что проблема с чтением и записью в одно и то же место одновременно.Но я совершенно уверен, что я не делаю этого здесь ... Плюс все, кажется, ведет себя как следует, за исключением фактической ошибки.

Когда обновляется combinedValues, это объект с ~ 300пары ключ / значение, это проблема?

1 Ответ

0 голосов
/ 03 октября 2018

Похоже, вашей функции не хватает памяти, каждая облачная функция выделяет память для своего выполнения.Вы можете попытаться увеличить размер стека с его значения по умолчанию (256 МБ) до 2 ГБ, перейдя в: Функции-> Панель инструментов, затем перейдите к своей проблемной функции и щелкните в правом меню «Подробная статистика использования»:

enter image description here

, затем в деталях вашей функции в облачной панели Google нажмите изменить:

enter image description here, затем увеличьте значение "memory"«выделено» на 2 ГБ (или более низкое достаточное значение):

enter image description here

Примечание: вы должны иметь в виду, что при росте данных вы можете превыситьсамый высокий предел, поэтому учитывайте это при запросе в облаке функций

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...