我有一个云函数,它是从客户端调用的,以便进行一些数据操作和创建。
一切都按预期进行,但是我无法避免反复出现的问题,有时是周期性的问题。 (虽然我有一种强烈的感觉冷启动也起作用)
问题:
await docRef.update({ ... })
中的第二个(最后一个)savePDF
完成,我可以记录返回的 writeTimestamp 数据。但是,Firestore 数据库永远不会用新数据更新。
如果我将 res.status(200).send('Requisition sent and saved')
包裹在 setTimeout
中,例如1000 毫秒,firebase 数据将使用 await docRef.update({ ... })
中最后一个 savePDF
提供的正确数据进行更新。
问题:
哪位大侠能赐教吗?除上述问题外,一切正常
代码(删除不需要的内容):
const admin = require('firebase-admin')
const functions = require('firebase-functions')
const cors = require('cors')({ origin: true })
const { config, isProd } = require('../../utils/config')
const { convertHTMLToPDF } = require('../../utils/convertHTMLToPDF')
let sendEmail = null
// if app already initialized with admin, use that one else setup new app
admin.apps.length
? admin.app()
: admin.initializeApp({
credential: admin.credential.cert(config.serviceAccount),
})
exports.createAndSendPDF = functions.runWith({
memory: '2GB',
}).region('europe-west3').https.onRequest((req, res) => {
cors(req, res, async () => {
// 1. Build file path
const storagePathRef = 'path/to/location/file.pdf'
// 2. Open bucket connection
const bucket = admin.storage().bucket(config.storage)
const fileRef = bucket.file(storagePathRef)
// conversion of HTML document to PDF with puppeteer (works as intended)
const pdf = await convertHTMLToPDF(htmlDocument)
// Must be completed before termination of cloud function
await Promise.all([
savePDF({ storagePathRef, fileRef }, pdf),
sendPDF(pdf)
])
res.status(200).send('Requisition sent and saved')
})
})
const savePDF = async (refs, pdf) => {
const {
storagePathRef,
fileRef,
} = refs
// Prop meta object
const initialPDFData = { /* just meta data */}
// Create meta data for firestore
const docRef = admin.firestore().collection('MyCollection').doc('DocID')
const docData = (await docRef.get()).data()
const existingPDFs = docData.pdfs || []
// Update field with new array
const initialMetaUpdatePromise = docRef.update({
pdfs: [...existingPDFs, initialPDFData],
})
// Save PDF
const fileSavePromise = fileRef.save(pdf, { resumable: false })
// Wait for initial meta update and file save to be done
await Promise.all([
initialMetaUpdatePromise,
fileSavePromise
])
// Get existing file meta
const { name, size, contentType } = (await fileRef.getMetadata())[0]
// Update meta object
const updatedProMeta = {
...initialPDFData,
name: name.split('/').slice(-1)[0],
size: Number(size) || -1,
type: contentType,
status: 'generated',
}
// Update requisition files list
await docRef.update({
requisitionFiles: [...existingPDFs, updatedProMeta],
})
}
const sendPDF = async (pdf) => {
if (!sendEmail) {
sendEmail = require('../../utils/sendgrid').sendEmail
}
sendEmail({ /* config for sending the mail */})
}