Как может один и тот же код в двух облачных функциях Firebase, которые различаются только триггером, давать разные результаты? - PullRequest
0 голосов
/ 13 июля 2020

У меня есть две функции: одна запускается каждое воскресенье в полночь UT C, а другая вызывается через запрос https. У них обоих одинаковый лог c внутри, буквально скопировано вставленное (за исключением https CF, который должен отвечать клиенту):

export const weeklyChallengeManagerFunction = functions.pubsub
    .schedule('every sun 00:00')
    .timeZone('Etc/GMT') // UTC
    .onRun(async () => {
        try {
            const resetProgress: UserChallenge = new UserChallenge()
            const challengeProgress: any = resetProgress.toFlatObject()

            const update = {
                challengeProgress,
            }
            await updateAllUsersInBatches(update)
            return
        } catch (err) {
            console.error(err)
            return
        }
    })

export const testWeeklyChallengeReset = functions.https.onRequest(async (req, res) => {
    try {
        const resetProgress: UserChallenge = new UserChallenge()
        const challengeProgress: any = resetProgress.toFlatObject()

        const update = {
            challengeProgress,
        }
        await updateAllUsersInBatches(update)
        res.json({ ok: true })
    } catch (err) {
        console.error(err)
        res.json({ ok: true, err })
    }
})

Эти функции должны сбрасывать challengeProgress поле для всех документов Firestore в коллекции users значения по умолчанию, которые определены в значениях по умолчанию конструктора класса UserChallenge.

updateAllUsersInBatches определяется следующим образом:

const updateAllUsersInBatches = async (update: any) => {
    const db = admin.firestore()

    const query = await db.collection('users').get()
    let batch = db.batch()

    query.docs.forEach(async (userSnap, index) => {
        if (index !== 0 && index % 500 === 0) {
            await batch.commit()
            batch = db.batch()
        }
        batch.update(userSnap.ref, update)
    })

    await batch.commit()
}

Наконец, в запланированном pubsub нет записей о тайм-ауте из-за холодного запуска или какой-либо ошибки. Зарегистрированы только два журнала: журнал «функция запущена» и запись «функция завершена нормально».

Сегодня утром был документ пользователя, который не был сброшен функцией pubsub (единственный активный пользователь, кстати, так как это не в производстве), но я скопировал тот же самый logi c в https CF, развернул, выполнил и все заработало.

Мой вопрос: Как это возможно? Что мне не хватает? В stackdriver тоже нет ошибок.

ПРИМЕЧАНИЕ: toFlatObject(): any - это функция, которая возвращает экземпляр объекта как простой объект вместо экземпляра класса. Это часть интерфейса, определенного мной как IFlatable, как обходной путь к тому факту, что firestore не может получать экземпляры классов и сохранять их напрямую в firestore. Их нужно как-то «сплющить» до простых javascript объектов:

toFlatObject(): any {
    return Object.assign({}, this)
}
...