Docs 菜单

Docs 主页Atlas App Services

处理函数中的错误

在此页面上

  • 基本错误处理
  • 查看日志
  • 重试函数
  • 在错误处理块中递归调用函数
  • 使用数据库触发器重试

本页介绍了如何处理 Atlas Function 中的错误。

注意

使用 AWS EventBridge 进行数据库触发器的自定义错误处理

您可以使用 AWS EventBridge 创建专门为数据库触发器创建的自定义错误处理程序。 有关详细信息,请参阅自定义错误处理。

您可以使用标准 JavaScript 错误处理技术(例如 try...catch 语句)来处理函数错误。

function willThrowAndHandleError() {
try {
throw new Error("This will always happen");
} catch (err) {
console.error("An error occurred. Error message:" + err.message);
}
}
exports = willThrowAndHandleError;

您可以在 App Services 日志中查看所有函数执行的记录,包括错误导致无法成功执行的记录。

根据调用函数的方式,它在日志中的显示方式会有所不同。例如,Atlas Triggers 调用的函数在日志中显示为“Triggers”,而从 Realm 客户端 SDK 中调用的函数在日志中显示为“Functions”。有关更多信息,请参阅日志条目类型文档

Atlas Functions 没有内置的重试行为。您可以添加自定义重试行为。例如,如果函数调用的第三方服务具有间歇性连接,并且您希望即使第三方服务器暂时关闭,函数也能重新执行,则您可能希望添加重试行为。

本节介绍了在函数中添加重试行为的以下策略:

您可以递归调用“函数”来处理可能失败的操作。

在高级别上,这一过程包括以下组成部分:

  • try 语句中执行要重试的操作,并在catch 语句中调用函数本身。

  • 要防止无限期执行,请设置最大重试次数。每次函数失败并进入 catch 语句时,增加当前重试次数的计数。在函数的当前重试次数达到最大重试次数时,停止递归执行。

  • 您可能还希望限制重试次数以减少某个时间范围内的执行总数。

下表描述了使用递归调用策略处理函数重试的一些优点和缺点。

优点
缺点
  • 所有重试逻辑都发生在一个函数内。

  • 函数可以在重试后返回一个值。

  • 最少的额外代码。

  • 所有重试必须在单个函数的最大执行时间内进行。

以下代码示例演示了通过在错误处理区块中使用递归来重试函数的实现。

// Utility function to suspend execution of current process
async function sleep(milliseconds) {
await new Promise((resolve) => setTimeout(resolve, milliseconds));
}
// Set variables to be used by all calls to `mightFail`
// Tip: You could also store `MAX_RETRIES` and `THROTTLE_TIME_MS`
// in App Services Values
const MAX_RETRIES = 5;
const THROTTLE_TIME_MS = 5000;
let currentRetries = 0;
let errorMessage = "";
async function mightFail(...inputVars) {
if (currentRetries === MAX_RETRIES) {
console.error(
`Reached maximum number of retries (${MAX_RETRIES}) without successful execution.`
);
console.error("Error Message:", errorMessage);
return;
}
let res;
try {
// operation that might fail
res = await callFlakyExternalService(...inputVars);
} catch (err) {
errorMessage = err.message;
// throttle retries
await sleep(THROTTLE_TIME_MS);
currentRetries++;
res = await mightFail(...inputVars);
}
return res;
}
exports = mightFail;

您还可以使用数据库触发器执行重试,并使用 MongoDB 集合跟踪以前失败的执行以重试函数。

在高级别上,这一过程包括以下组成部分:

  • 主函数执行您想要重试的逻辑,包装在处理函数中(请参见下面的要点)。

  • 失败执行跟踪器 MongoDB 集合;用于跟踪主函数的失败执行。

  • 处理程序函数;用于调用主函数,并在函数失败时将其记录到失败执行跟踪器集合中。

  • 数据库触发器函数;每当处理程序函数将错误添加到失败执行跟踪器集合时,就会重新运行处理程序函数。

您可以使用一组处理程序函数、执行跟踪器集合和数据库触发器函数来支持多个主函数。

优点
缺点
  • 每次重试都是其自己的函数执行,具有自己的最大执行时间和资源。

  • 如果重试函数,则无法返回值。

  • 每个函数调用都需要调用函数两次,一次用于函数本身,一次用于重试处理程序。

  • 更复杂的逻辑,可能更难编写、调试和监控。

1

首先,创建调用主函数的处理程序函数 handleRetry

handleRetry 接受以下参数:

范围
类型
说明
functionToRetry
JavaScript 函数
要重试的函数。
functionName
字符串
您要重试的函数名称。
operationId
ObjectId
主函数执行的唯一标识符,包括重试。
previousRetries
数值
以前尝试执行主函数的次数。
...args
其余参数
传递给主函数的不确定数量的参数。

handleRetry 执行以下操作:

  1. 尝试在 try 语句中执行 functionToRetry。如果执行成功,则 handleRetry 将返回由以下内容返回的值 functionToRetry

  2. 如果在上一步中执行 functionToRetry 而引发错误,则catch 语句按如下方式处理该错误:

    1. 检查以前的重试次数是否等于允许的最大重试次数。如果两个数字相同,则函数会发生错误,因为已达到最大重试次数。该函数不再尝试重试。

    2. 创建一个函数执行日志条目对象以插入到数据库中。

    3. 获取对失败执行跟踪器集合的引用。

    4. 将函数日志执行日志条目插入失败的执行跟踪器集合中。此插入操作会导致数据库触发器函数(您将在下一步中触发该函数)。

主函数是作为 functionToRetry 参数传递的。handleRetry 尝试执行主函数。如果执行失败,该函数尝试重试主函数。

2

现在,为触发器调用的函数添加代码。

retryOperation 函数将重试处理程序发布到失败执行跟踪器集合的文档作为 logEntry 参数。然后,retryOperation 使用来自 logEntry 的信息通过 context.functions.execute() 调用主函数。

3

现在您有了函数处理程序和重试数据库触发器函数,您可以编写主函数。

在以下示例中,函数在执行加法时随机出现错误。执行此逻辑的 JavaScript 函数如下:

  • getRandomOneTwoThree():用于为示例生成错误的辅助函数。

  • additionOrFailure():使用主逻辑的函数。

调用重试处理程序包装的 additionOrFailure() 是在导出的函数 additionWithRetryHandler() 中进行的。所有使用重试处理函数的函数应类似于该函数。

必须包含正确的参数,才能使此函数与其余重试逻辑一起工作。这些参数包括:

范围
类型
说明
...args
其余参数
使用主逻辑传递给函数的零个或多个参数。在本例中,additionOrFailure()num1num2 这两个数字进行相加。
operationId
函数调用和重试的唯一标识符。将默认值设置为 new BSON.ObjectId()
retries
数值
将默认值设置为 0。

additionWithRetryHandler 正文是 context.functions.execute() 调用的重试处理程序 handleRetry,而该重试处理程序又会调用 additionOrFailure。您传递给 context.functions.execute() 的参数如下所示:

参数
类型
说明
"handleRetry"
字符串
您定义的函数名称,用于调用主函数,并在主函数未正确执行时发布到重试日志。
additionOrFailure
JavaScript 函数
handleRetry() 调用的主函数。
operationId
BSON.ObjectId
作为参数从 additionWithRetryHandler()operationId 参数中传入。
retries
数值
作为参数从 additionWithRetryHandler()retries 参数中传入。
...args
展开参数
使用主逻辑传递给函数的零个或更多参数。作为参数从 additionWithRetryHandler()...args 参数中传入

现在,在您调用 additionWithRetryHandler 时,如果失败,函数将重试。

← 测试 Atlas Function