英文:
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
参数只包含了认证详情
所以我们必须在函数外部进行跟踪。
这个示例会在每次重试、成功或完全失败时更新一个 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
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 '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 {
// Call the API
await apiCall();
} catch (error) {
// Get the functionStatus someTask doc
const someTaskDoc = await admin
.firestore()
.collection('functionStatus')
.doc('someTask')
.get();
if (someTaskDoc.data()?.retries < 5) {
// Update the retry count because we have retries left
await admin
.firestore()
.collection('functionStatus')
.doc('someTask')
.update({ retries: increment(1) });
} else {
// Update the status to failed because retries are spent
await admin
.firestore()
.collection('functionStatus')
.doc('someTask')
.update({ status: 'failed' });
}
// Throw the error to start the retry (or if retries are spent kill the function completely)
throw new functions.https.HttpsError('unknown', 'someTask error');
}
// Everything worked. Mark function as successful
await admin
.firestore()
.collection('functionStatus')
.doc('someTask')
.update({ status: 'success' });
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论