我有两个不同的云函数,它们偶尔会出现相同的错误。
一个是聚合一些计数器的firestore触发器,另一个是清理旧数据的计划任务。
我似乎看不出错误的任何模式,也没有很多信息。此外,我没有找到很多在这里或与谷歌搜索。它只是偶尔发生,也许每隔几天,或者几个星期,没有错误。它发生的时间大约不到函数运行的2%。
我对firebase和使用async await比较陌生,所以它可能与此相关(async/await)。
以下函数之一的错误和代码。
{ Error
at Http2CallStream.call.on (/srv/node_modules/@grpc/grpc-js/build/src/client.js:96:45)
at emitOne (events.js:121:20)
at Http2CallStream.emit (events.js:211:7)
at process.nextTick (/srv/node_modules/@grpc/grpc-js/build/src/call-stream.js:71:22)
at _combinedTickCallback (internal/process/next_tick.js:132:7)
at process._tickDomainCallback (internal/process/next_tick.js:219:9)
code: 13,
details: '',
metadata: Metadata { options: undefined, internalRepr: Map {} } }
export const clearOldAvailabilityInternal = async () => {
const limit = 500;
let vehicleAvailabilityIds: string[] = [];
let vehicleTypeAvailabilityIds: string[] = [];
const now = new Date();
const twoWeeksAgo = moment(now).subtract(14, "days");
do {
vehicleAvailabilityIds = [];
const batch1 = db.batch();
const vehicleAvailabilityDocs = await db.collection('vehicleAvailability')
.where('dateInterval', '<', twoWeeksAgo.toDate())
.limit(limit)
.get();
for (const doc of vehicleAvailabilityDocs.docs) {
vehicleAvailabilityIds.push(doc.id);
};
for(const id of vehicleAvailabilityIds) {
const deleteRef = db.doc(`vehicleAvailability/${id}`)
batch1.delete(deleteRef);
}
try {
const result = await batch1.commit();
console.log('Deleted ' + vehicleAvailabilityIds.length + ' vehicleAvailability documents');
} catch (err) {
console.log(err);
throw err;
}
}
while (vehicleAvailabilityIds.length === limit)
do {
vehicleTypeAvailabilityIds = [];
const batch2 = db.batch();
const vehicleTypeAvailabilityDocs = await db.collection('vehicleTypeAvailability')
.where('dateInterval', '<', twoWeeksAgo.toDate())
.limit(limit)
.get();
for (const doc of vehicleTypeAvailabilityDocs.docs) {
vehicleTypeAvailabilityIds.push(doc.id);
};
for(const id of vehicleTypeAvailabilityIds) {
const deleteRef = db.doc(`vehicleTypeAvailability/${id}`)
batch2.delete(deleteRef);
}
try {
const result = await batch2.commit();
console.log('Deleted ' + vehicleTypeAvailabilityIds.length + ' vehicleTypeAvailability documents');
} catch (err) {
console.log(err);
throw err;
}
}
while (vehicleTypeAvailabilityIds.length === limit)
console.log('clearOldAvailabilityInternal complete');
return Promise.resolve(true);
}
编辑:
通过捕获错误发生的地方并记录它,我在note字段中获得了更多的细节。“在重试方法中发生了不属于瞬态的异常”,然后我找到了下面的答案。
{ Error
at Http2CallStream.call.on (/srv/node_modules/@grpc/grpc-js/build/src/client.js:96:45)
at emitOne (events.js:121:20)
at Http2CallStream.emit (events.js:211:7)
at process.nextTick (/srv/node_modules/@grpc/grpc-js/build/src/call-stream.js:71:22)
at _combinedTickCallback (internal/process/next_tick.js:132:7)
at process._tickDomainCallback (internal/process/next_tick.js:219:9)
code: 13,
details: '',
metadata: Metadata { options: undefined, internalRepr: Map {} },
note: 'Exception occurred in retry method that was not classified as transient' }
似乎是FireStore当前已知的问题。可能使用FirebaseAdminV8。他们正试图解决这一问题,但“可能需要一些时间”。
https://github.com/firebase/firebase-functions/issues/536
2019年8月2日:https://github.com/firebase/firebase-functions/issues/536#issuecomment-517461545
我们的后端团队相信他们知道问题的根本原因,但是要在所有的生产环境中解决这个问题可能需要一段时间。
2019年10月12日:https://github.com/firebase/firebase-functions/issues/536#issuecomment-541130536
我们正在继续改进网络堆栈中使用的库,但即使使用最新的@grpc/grpc-js模块,您仍可能遇到偶尔的网络问题。