如何追踪 Firebase 函数任务队列已耗尽所有重试次数?

huangapple go评论42阅读模式
英文:

How to track when Firebase Functions Task Queues have exhausted all retries?

问题

我正在使用Firebase Functions任务队列来调用多个API端点。

每个函数被设置为在遇到错误时重试5次。

现在我想要跟踪函数是否成功完成或完全失败(即所有重试都耗尽并且函数仍然抛出错误)。

我想要跟踪这一点,以便如果它完全失败,我可以更新Firestore文档或发送某种警报。

例如,这是一个任务队列函数,我该如何添加上述功能?

export const someTask = functions.tasks
  .taskQueue({
    retryConfig: {
      maxAttempts: 5,
      minBackoffSeconds: 60,
    },
    rateLimits: {
      maxConcurrentDispatches: 1,
    },
  })
  .onDispatch(
    async () => {
      try {
        // 调用API
        await apiCall();
        return;
      } catch (error) {
        // 抛出错误,以便任务队列重试
        throw new functions.https.HttpsError(
          'unknown',
          'someTask error'
        );
      }
    }
  );
英文:

I am using Firebase Functions Task Queues to call numerous API endpoints.

Each function is set to retry 5 times if it encounters an error.

Now I want to track if the function completes successfully or fails completely (i.e. all retries are exhausted and the function still throws an error).

I want to track this so that if it fails completely I can update a Firestore document or send an alert of some kind.

For example, here is a Task Queue function, how do I add the above functionality?

export const someTask = functions.tasks
  .taskQueue({
    retryConfig: {
      maxAttempts: 5,
      minBackoffSeconds: 60,
    },
    rateLimits: {
      maxConcurrentDispatches: 1,
    },
  })
  .onDispatch(
    async () => {
      try {
        // Call the API
        await apiCall();
        return;
      } catch (error) {
        // Throw error so that the Task Queue will retry
        throw new functions.https.HttpsError(
          'unknown',
          'someTask error'
        );
      }
    }
  );

答案1

得分: 4

这不能在onDispatch中原生实现,因为onDispatch提供的context参数只包含了认证详情 如何追踪 Firebase 函数任务队列已耗尽所有重试次数?

所以我们必须在函数外部进行跟踪。

这个示例会在每次重试、成功或完全失败时更新一个 Firestore 文档。有一个名为 functionStatus 的 Firestore 集合,每个文档的ID等于您要跟踪的函数的名称。在这个示例中,文档ID将是 someTask。这种命名约定使得更新状态更容易。

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';

const increment = admin.firestore.FieldValue.increment;

export const someTask = functions.tasks
  .taskQueue({
    retryConfig: {
      maxAttempts: 5,
      minBackoffSeconds: 60,
    },
    rateLimits: {
      maxConcurrentDispatches: 1,
    },
  })
  .onDispatch(async () => {
    try {
      // 调用 API
      await apiCall();
    } catch (error) {
      // 获取 functionStatus someTask 文档
      const someTaskDoc = await admin
        .firestore()
        .collection('functionStatus')
        .doc('someTask')
        .get();

      if (someTaskDoc.data()?.retries < 5) {
        // 更新重试计数,因为我们还有重试次数
        await admin
          .firestore()
          .collection('functionStatus')
          .doc('someTask')
          .update({ retries: increment(1) });
      } else {
        // 将状态更新为失败,因为重试次数已用完
        await admin
          .firestore()
          .collection('functionStatus')
          .doc('someTask')
          .update({ status: 'failed' });
      }

      // 抛出错误以开始重试(或者如果重试次数用完,则完全终止函数)
      throw new functions.https.HttpsError('unknown', 'someTask error');
    }

    // 一切正常工作。将函数标记为成功
    await admin
      .firestore()
      .collection('functionStatus')
      .doc('someTask')
      .update({ status: 'success' });
  });
英文:

This cannot be done natively with because the context argument provided by onDispatch only holds authentication details 如何追踪 Firebase 函数任务队列已耗尽所有重试次数?

So we have to track it outside the function.

This example updates a Firestore document for each retry, success, or complete failure. There is a Firstore collection named functionStatus and the ID of each document is equal to the name of the function you want to track. In this example the document ID would be someTask. This naming convention makes it easier to update the status.

import * as functions from &#39;firebase-functions&#39;;
import * as admin from &#39;firebase-admin&#39;;

const increment = admin.firestore.FieldValue.increment;

export const someTask = functions.tasks
  .taskQueue({
    retryConfig: {
      maxAttempts: 5,
      minBackoffSeconds: 60,
    },
    rateLimits: {
      maxConcurrentDispatches: 1,
    },
  })
  .onDispatch(async () =&gt; {
    try {
      // Call the API
      await apiCall();
    } catch (error) {
      // Get the functionStatus someTask doc
      const someTaskDoc = await admin
        .firestore()
        .collection(&#39;functionStatus&#39;)
        .doc(&#39;someTask&#39;)
        .get();

      if (someTaskDoc.data()?.retries &lt; 5) {
        // Update the retry count because we have retries left
        await admin
          .firestore()
          .collection(&#39;functionStatus&#39;)
          .doc(&#39;someTask&#39;)
          .update({ retries: increment(1) });
      } else {
        // Update the status to failed because retries are spent
        await admin
          .firestore()
          .collection(&#39;functionStatus&#39;)
          .doc(&#39;someTask&#39;)
          .update({ status: &#39;failed&#39; });
      }

      // Throw the error to start the retry (or if retries are spent kill the function completely)
      throw new functions.https.HttpsError(&#39;unknown&#39;, &#39;someTask error&#39;);
    }

    // Everything worked. Mark function as successful
    await admin
      .firestore()
      .collection(&#39;functionStatus&#39;)
      .doc(&#39;someTask&#39;)
      .update({ status: &#39;success&#39; });
  });

huangapple
  • 本文由 发表于 2023年2月19日 16:21:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75498837.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定