У меня есть две функции: одна запускается каждое воскресенье в полночь 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)
}