Amazon web services AWS Step函数:如何访问在catch块中生成异常的状态输入?
我正在尝试使用状态机语言中定义的并行块和Catch块在我的step函数流中添加错误处理 以下是我的step功能流程图: 因为我希望所有步骤函数都有一个公共错误处理程序,所以我将它们包装在一个并行块中,并添加了一个公共Catch块来捕获任何步骤函数中的任何错误。通过查看各种示例和博客,我遵循了link并实现了类似的方法 我观察到的是,每当任何状态引发异常时,控件都会进入catch块。catch块的输入是引发的异常,该异常包含JSON对象中的错误和原因。由于我希望错误与传递到该状态的输入一起出现,我在catch块中添加了ResultPath作为“$.error”。下面是定义状态机的JSON规范Amazon web services AWS Step函数:如何访问在catch块中生成异常的状态输入?,amazon-web-services,error-handling,try-catch,aws-step-functions,state-machine-workflow,Amazon Web Services,Error Handling,Try Catch,Aws Step Functions,State Machine Workflow,我正在尝试使用状态机语言中定义的并行块和Catch块在我的step函数流中添加错误处理 以下是我的step功能流程图: 因为我希望所有步骤函数都有一个公共错误处理程序,所以我将它们包装在一个并行块中,并添加了一个公共Catch块来捕获任何步骤函数中的任何错误。通过查看各种示例和博客,我遵循了link并实现了类似的方法 我观察到的是,每当任何状态引发异常时,控件都会进入catch块。catch块的输入是引发的异常,该异常包含JSON对象中的错误和原因。由于我希望错误与传递到该状态的输入一起出现,
{
"StartAt": "Try",
"States": {
"Try": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "Step-1",
"States": {
"Step-1": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:1234:function:step-1-lambda",
"Next": "Step-2"
},
"Step-2": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.some_variable",
"StringEquals": "some_string",
"Next": "Step-3"
},
{
"Variable": "$.some_variable",
"StringEquals": "some_other_string",
"Next": "Step-4"
}
],
"Default": "Step-6"
},
"Step-3": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:1234:function:step-3-lambda",
"Next": "Step-6"
},
"Step-4": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:1234:function:step-4-lambda",
"Next": "Step-6"
},
"Step-6": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:1234:function:step-6-lambda",
"End": true
}
}
}
],
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "ErrorHandler"
}
],
"Next": "UnwrapOutput"
},
"UnwrapOutput": {
"Type": "Pass",
"InputPath": "$[0]",
"End": true
},
"ErrorHandler": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:1234:function:step-7-lambda",
"End": true
}
}
}
例如,考虑STEP4生成异常。此状态的输入为:
{
"foo": "abc",
"bar": "def"
}
触发状态机的输入为:
{
"boo": "jkl",
"baz": "mno"
}
在ErrorHandler中,当步骤4生成异常时,我希望ErrorHandler状态的输入为:
{
"foo": "abc",
"bar": "def",
"error": {
"Error": "SomeError",
"Cause": "SomeCause"
}
}
但是,接收的输入包含用于触发流的原始输入
{
"boo": "jkl",
"baz": "mno",
"error": {
"Error": "SomeError",
"Cause": "SomeCause"
}
}
我需要访问导致ErrorHandler中异常的状态的输入字段。它使用“$”提供用于触发流的输入。有什么办法可以做到这一点吗
任何帮助都将不胜感激,我一直在努力解决这个问题。我只晚了10个月,没有那么多哈哈,但我希望你已经找到了解决办法,无论如何,我会分享我的两分钱,这样我可以帮助另一个开发人员,或者更好,有人可以告诉我更好的方法 首先,让我们看看我们有哪些场景:
- Sych作业执行
- 异步作业执行
- 基本上,将自定义的try-catch添加到所有作业资产中,换句话说,lambda函数应该抛出一个错误,提供有关正在使用它的作业的信息。我不太喜欢这种方法,因为为了在状态机中实现一些逻辑,您正在更改隔离的函数。最后,您将耦合两个独立的概念,您的状态机不需要外部工具来操作和记录其自身的上下文。我在这里可能错了,但那只是我的两分钱,请随意冒犯我的家人(只是开玩笑,但请随意纠正我)
- 在状态机中添加“addCatch”时,默认行为是覆盖步骤输入的错误输出。要解决这个问题,您只需要更改addCatch resultPath,这样您就可以将错误输出与步骤输入一起存储 例:“捕获”:[ { “ErrorEquals”:[“States.All”], “下一步”:“ErrorHandler” “结果路径”:“$。错误信息” } ]
- 通过这种方式,您将能够访问errorHandlerJob中的步骤输入,这意味着您可以始终将步骤名称传递到下一个步骤输入,这样您将始终知道哪个作业失败。您不会通过直接更改lambda函数来实现这一点,而是通过使用作业的属性来解决耦合问题!但这在异步场景中不起作用,我将在下面解释
- 前面的解决方案在这里不起作用,因为在这种情况下,您只能访问原始输入,因为您使用的是并行分支。所以我在这里所做的与上一个案例相似。我在并行分支中添加了Pass状态,这些Pass状态负责同步调用我的作业,而且我的所有作业都有自己的errorHandlingJob,没有不同的LAMBDA函数。我不会在AWS上创建新的资源,只有一个HandleError Lambda函数,所以我可以将监控重点放在该特定函数上。但是,我使用它为状态机必须执行的每个作业创建一个errorHandlingJob
- 缺点是你的状态机现在有一个巨大的图形,但好的方面是你现在可以记录哪个作业失败了
import { Construct, Duration } from 'monocdk'
import { NodejsFunction } from 'monocdk/aws-lambda-nodejs'
import { Pass,Result, Parallel, ParallelProps } from 'monocdk/aws-stepfunctions'
import { LambdaInvoke } from 'monocdk/aws-stepfunctions-tasks'
export interface DefinitionProps {
sonosEnvironment: string
region: string
accountNumber: string
}
export class ParallelStateMachineCatch extends Parallel {
private errorHandler: NodejsFunction
constructor(scope: Construct, id: string, props: ParallelProps, errorHandler: NodejsFunction) {
super(scope, id, props)
this.errorHandler = errorHandler
}
branchCatch(task: LambdaInvoke): ParallelStateMachineCatch {
const randomId = Math.random().toString().replace('0.', '')
const passInputJob = ParallelStateMachineCatch.generatePassInput(this, task.id, randomId)
const handleErrorJob = ParallelStateMachineCatch.generateHandleErrorJob(this, this.errorHandler, randomId)
const resultPath = '$.error-info'
this.branch(passInputJob.next(task.addCatch(handleErrorJob, { resultPath })))
return this
}
private static generateHandleErrorJob(scope: Construct, errorHandler: NodejsFunction, randomId: string): LambdaInvoke {
return new LambdaInvoke(scope, `Handle Error ${ randomId }`, {
lambdaFunction: errorHandler,
outputPath: '$.Payload',
timeout: Duration.seconds(5),
})
}
private static generatePassInput(scope: Construct, stepName: string, randomId: string): Pass {
return new Pass(scope, `Pass Input ${ randomId }`, {
resultPath: '$.step-info',
result: Result.fromObject({
name: stepName
})
})
}
}
无论如何,我希望我能在这方面帮助别人,这就是我解决这个问题的方法。请随意教我更好的方法!Tks
祝你好运,好代码谢谢你提供图表和详细信息。我相信下面这样的东西可以帮助你:或者
this.definition = new ParallelStateMachineCatch(this,
}, handleErrorFunction)
.branchCatch(job1)
.branchCatch(job2)
.branchCatch(job3)
.branchCatch(job4)
.branchCatch(job5)
.branchCatch(job6)
.next(final)
import { Construct, Duration } from 'monocdk'
import { NodejsFunction } from 'monocdk/aws-lambda-nodejs'
import { Pass,Result, Parallel, ParallelProps } from 'monocdk/aws-stepfunctions'
import { LambdaInvoke } from 'monocdk/aws-stepfunctions-tasks'
export interface DefinitionProps {
sonosEnvironment: string
region: string
accountNumber: string
}
export class ParallelStateMachineCatch extends Parallel {
private errorHandler: NodejsFunction
constructor(scope: Construct, id: string, props: ParallelProps, errorHandler: NodejsFunction) {
super(scope, id, props)
this.errorHandler = errorHandler
}
branchCatch(task: LambdaInvoke): ParallelStateMachineCatch {
const randomId = Math.random().toString().replace('0.', '')
const passInputJob = ParallelStateMachineCatch.generatePassInput(this, task.id, randomId)
const handleErrorJob = ParallelStateMachineCatch.generateHandleErrorJob(this, this.errorHandler, randomId)
const resultPath = '$.error-info'
this.branch(passInputJob.next(task.addCatch(handleErrorJob, { resultPath })))
return this
}
private static generateHandleErrorJob(scope: Construct, errorHandler: NodejsFunction, randomId: string): LambdaInvoke {
return new LambdaInvoke(scope, `Handle Error ${ randomId }`, {
lambdaFunction: errorHandler,
outputPath: '$.Payload',
timeout: Duration.seconds(5),
})
}
private static generatePassInput(scope: Construct, stepName: string, randomId: string): Pass {
return new Pass(scope, `Pass Input ${ randomId }`, {
resultPath: '$.step-info',
result: Result.fromObject({
name: stepName
})
})
}
}