我正在尝试在调整一组图像大小时更新文档,以显示进度并跟踪是否有任何图像无法转换。
我们在 dir 中几乎没有图像,其中 dir 是文档 ID。使用文档 ID,我们必须更新该文档。我们必须设置状态字段,状态包含已转换或转换失败信息的对象。 {图像:路径,处理:字符串}
看起来像 { ... 地位 : [ 文件名1:{...}, 文件名2:{...} ] }
但是当我上传 5 到 10 个图像时,它只在状态字段中设置前 4-5 个图像信息。它在将最后一个图像信息写入状态之前暂停。
虽然我尝试简单地用状态中的新数据替换旧数据,但这意味着只有单个对象会出现在此处并相应地发生更改。这在大多数情况下都有效,尽管我看到极少数情况下也失败,但大多数情况下它都有效。
async function updateDoc({filePath, metadata}) {
const [docId, fileName] = filePath.split('/');
const db = admin.firestore();
const collectionRef = db.collection(COLLECTION_PACKS).doc(docId);
const stickersRef = collectionRef.collection(COLLECTION_STICKERS);
let attempts = 0;
const maxAttempts = 5;
while (attempts < maxAttempts) {
try {
await db.runTransaction(async (transaction) => {
const updatedStatus = {};
updatedStatus[fileName] = metadata;
// Update the document with the new status and progress
transaction.update(collectionRef, {
status: updatedStatus,
});
});
console.log("Updated document for", filePath);
break; // Exit the loop if successful
} catch (error) {
attempts++;
console.error(`Error updating document (attempt ${attempts}):`, error);
if (attempts >= maxAttempts) {
throw error; // Re-throw the error after max attempts
}
await new Promise(resolve => setTimeout(resolve, 1000 * attempts)); // Exponential backoff
}
}
}
async function updateMeta({filePath, process, valid, error}){
// console.log("updateMeta ",filePath)
let metadata = { process, valid }
if (error) { metadata.error = error; }
await bucket.file(filePath).setMetadata({
metadata: metadata
})
await updateDoc({ filePath, metadata})
}
不需要使用
db.runTransaction()
,因为您没有在更新中使用任何旧值,因此它只是添加了更多不必要的处理。
如果您的数据结构实际上是
{ ... status : { filename1:{...}, filename2:{...} } }
(请注意,我用大括号替换了方括号,我相信您的意思是对象而不是数组),那么您可以简单地更新嵌套路径,而无需使用事务。也无需重试:
// this is a docRef, not a colRef as in your example
const docRef = db.collection(COLLECTION_PACKS).doc(docId);
const update = {
[`status.${fileName}`]: metadata,
};
await docRef.update(update);