为什么此Firebase Cloud Function函数产生错误“错误:函数崩溃超出请求范围函数调用被中断。”

时间:2019-07-19 16:35:50

标签: typescript firebase async-await google-cloud-functions

我有一个Firebase Cloud功能,该功能每天在股市开盘时触发一次。似乎在运行20%的时间时会产生错误。

错误说:“错误:函数崩溃超出了请求范围。函数调用被中断。”

export async function cleanIntraweek() {
  console.log(`cleanIntraweek() started`)

  const min_date_key = moment().tz("America/New_York").subtract(7, 'day').format()

  console.log(`min_date_key: ${min_date_key}`)

  //helper async function to grab some data
  const enabled_stock_keys = await FirebaseObjectFetchService.getStockKeys(true)

  const fetch_intraweek_dataset_promises: Promise<any>[] = []
  const clear_data_promises: Promise<any>[] = []

  for (const stock_key of enabled_stock_keys) {
    const fetch_intraweek_dataset_promise =
      db
        .ref(`charts/${stock_key}/intraweek_v3`)
        .orderByKey()
        .endAt(min_date_key)
        .once("value")
        .then((snapshot) => {
          snapshot.forEach((child_snapshot) => {
            const clear_data_promise = child_snapshot.ref.remove()
            clear_data_promises.push(clear_data_promise)
            return false
          });
        })
    fetch_intraweek_dataset_promises.push(fetch_intraweek_dataset_promise)
  }

  console.log("waiting on fetch_intraweek_dataset_promises")
  await Promise.all(fetch_intraweek_dataset_promises)

  console.log("waiting on clear_data_promises")
  await Promise.all(clear_data_promises).then(() => {console.log("cleanIntraweek() finished")})

  return null
}

我不记得在Node 6引擎上运行云功能时遇到此错误。从Node 8引擎(当前)恢复为Node 6引擎不是解决方案,因为Firebase Cloud Functions会在一年内取消对Node 6引擎的支持。

最近一次错误运行的日志是: firebase logs

我见过this post,但是据我所知,我没有在函数返回之前没有等待的任何诺言。

1 个答案:

答案 0 :(得分:0)

此错误通常意味着您应该运行一些异步代码,并在该功能应该完全完成之后引发了执行。这意味着您实际上没有正确处理函数中的所有promise。问题似乎在这里发生:

    .then((snapshot) => {
      snapshot.forEach((child_snapshot) => {
        const clear_data_promise = child_snapshot.ref.remove()
        clear_data_promises.push(clear_data_promise)
        return false
      });
    })

您有一个Promise回调,它异步创建更多的Promise以删除子节点。但是,这里没有任何东西可以保证clear_data_promises会在之前完全填充,之后再等待承诺列表。换句话说,await Promise.all(clear_data_promises)可以在保证clear_data_promises完全填充之前执行,因为forEach lambda本身不会阻塞每个操作的结果。

您要做的是确保上面的then回调函数返回一个promise,该promise跟踪forEach Labmda内部的所有内部promise。仅在所有下级工作完成后,fetch_intraweek_dataset_promise承诺才能得到解决。与此类似:

    .then((snapshot) => {
      const clear_data_promises = []
      snapshot.forEach((child_snapshot) => {
        const clear_data_promise = child_snapshot.ref.remove()
        clear_data_promises.push(clear_data_promise)
        return false
      });
      return Promise.all(clear_data_promises)
    })

然后,您不必稍后再等待该阵列。一切都将通过fetch_intraweek_dataset_promises解决。