提问者:小点点

如何确定firebase云函数间歇性错误的原因


我有两个不同的云函数,它们偶尔会出现相同的错误。

一个是聚合一些计数器的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' }

共1个答案

匿名用户

似乎是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模块,您仍可能遇到偶尔的网络问题。