Go Lambda 的 AWS Step Function 错误处理

AWS Step Function error handling for Go Lambda

根据 Go 处理程序 return 编辑的错误,我找不到如何在 Step 函数中定义错误条件匹配器的详细说明。

handler 是一个标准的 Go 函数,return 是一个 error 如果它从上游服务获得 503:

func HandleHotelBookingRequest(ctx context.Context, booking HotelBookingRequest) (
    confirmation HotelBookingResponse, err error) {
    
    ...
        if statusCode == http.StatusServiceUnavailable {
            err = errors.New("TransientError")
        } else {

我可以控制函数 return 的内容,以及它如何格式化字符串;我找不到任何关于在这里使用什么的真实信息(或者在 Catch 子句中,就此而言),所以这与上面的匹配:

      "Retry": [
        {
          "ErrorEquals": [
            "TransientError"
          ],
          "BackoffRate": 1,
          "IntervalSeconds": 1,
          "MaxAttempts": 3,
          "Comment": "Retry for Transient Errors (503)"
        }
      ]

当我在控制台中测试 Lambda 时,这是我在上游 returns a 503:

时得到的(如预期的那样)
{
  "errorMessage": "TransientError",
  "errorType": "errorString"
}

我有一个明显的印象(但不太确定如何验证这一点),如果我更改为:

          "ErrorEquals": [
            "errorString"
          ],

Retry 有效(至少,查看 CloudWatch 日志,我可以看到正在记录 transient error,但 Step 函数最终成功)。

我找不到太多关于此的文档但是:

  1. 是否可以匹配实际的错误消息(我看到 API 网关允许使用 RegEx 做到这一点);
  2. 如果那不可能,我应该 return 不同的“错误类型”,而不是 error

提前致谢!

终于解开了谜语;最后,它是微不足道的,并且与 JavaScript 方法完全相同((a)给了我提示,(b)在示例中被广泛记录);但是,由于我无法在任何地方找到特定于 Go 的答案(在 AWS - 扩展、良好、详细的文档中,Google,此处)我将其发布在这里以供将来参考。

TL;DR - 定义您自己的 error 接口实现和 return 该类型的对象,而不是沼泽标准 fmt.Error(),然后在 ErrorEquals 子句中使用类型名称。

this gist 中显示了一个非常基本的示例实现。

为了测试这一点,我创建了一个 ErrorStateMachine(JSON 定义在同一要点中)并根据 ErrorEquals 类型选择了不同的捕手:

        {
          "ErrorEquals": [
            "HandlerError"
          ],
          "Next": "Handler Error"
        }

使用不同的 Outcome 输入测试阶跃函数,导致选择不同的路径。

我猜让我失望的是我是 Go 的相对初学者,我没有意识到 errorStringerror 接口的实际类型 return由 errors.New() 方法编辑,在 fmt.Errorf():

中使用
// in errors/errors.go

// errorString is a trivial implementation of error.
type errorString struct {
    s string
}

我天真地以为这只是 AWS 命名的东西。

一个有趣的转折(不是很理想)是实际的错误消息被“包装”在 Step 函数输出中,并且在后续步骤中解析起来可能有点麻烦:

{
  "Error": "HandlerError",
  "Cause": "{\"errorMessage\":\"error from a failed handler\",\"errorType\":\"HandlerError\"}"
}

如果将实际的错误消息(由 Error() 生成)直接发送到 Cause 字段.

希望其他人觉得这很有用,而不必像我一样在这上面浪费时间。