[英]AWS Step Functions: How to access the input of the state that generated an exception in a catch block?
I am trying to add error handling in my step function flow using the Parallel and Catch blocks as defined in the State Machine Language.我正在尝试使用 State 机器语言中定义的 Parallel 和 Catch 块在我的步骤 function 流程中添加错误处理。
Following is the flow diagram of my step functions:以下是我的步骤功能的流程图:
Since I want a common error handler for all the step functions, I have wrapped them in a Parallel block and added a common Catch block to catch any errors in any of the step functions.因为我想要一个用于所有步进函数的通用错误处理程序,所以我将它们包装在一个 Parallel 块中,并添加了一个通用 Catch 块来捕获任何步进函数中的任何错误。 On looking through various examples and blogs, I followed this link and implemented a similar approach.
在浏览各种示例和博客时,我遵循了这个链接并实现了类似的方法。
What I observe is that, whenever any state raises an exception, the control goes into the catch block.我观察到的是,每当任何 state 引发异常时,控件都会进入 catch 块。 The input to the catch block is the exception that was raised containing an Error and Cause in a JSON object.
catch 块的输入是在 JSON object 中引发的包含错误和原因的异常。 Since I wanted the error along with the input that was passed to that state, I added the ResultPath as "$.error" in the catch block.
由于我想要错误以及传递给 state 的输入,因此我在 catch 块中将 ResultPath添加为“$.error” 。 Following is the JSON spec that defines the state machine.
以下是定义 state 机器的 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
}
}
}
For example, consider that Step-4 generates an exception.例如,考虑第 4 步生成异常。 The input to this state is:
这个 state 的输入是:
{
"foo": "abc",
"bar": "def"
}
The input with which the state machine is triggered is:触发 state 机器的输入是:
{
"boo": "jkl",
"baz": "mno"
}
In the ErrorHandler, as Step-4 generates an exception I was expecting that the input to the ErrorHandler state would be:在 ErrorHandler 中,当第 4 步生成异常时,我期望 ErrorHandler state 的输入为:
{
"foo": "abc",
"bar": "def",
"error": {
"Error": "SomeError",
"Cause": "SomeCause"
}
}
However, the input received consists of the original input that is used to trigger the flow.但是,接收到的输入包含用于触发流的原始输入。
{
"boo": "jkl",
"baz": "mno",
"error": {
"Error": "SomeError",
"Cause": "SomeCause"
}
}
I need to access the input fields of the state that caused the exception in the ErrorHandler.我需要访问导致 ErrorHandler 异常的 state 的输入字段。 Using "$" it provides the input that was used to trigger the flow.
使用“$”它提供用于触发流程的输入。 Is there a way I can achieve this?
有没有办法可以做到这一点?
Any help would be appreciated, I am trying to figure this out since a long time.任何帮助将不胜感激,我一直在努力解决这个问题。
I'm only 10 months late, not that much haha but I hope you have already found a solution for this, In any case, I will share my two cents so I can help another dev, or even better, someone can show me a better way to do this!我只晚了 10 个月,没那么多哈哈,但我希望你已经找到了解决方案,无论如何,我会分享我的两分钱,以便我可以帮助另一个开发人员,或者更好,有人可以告诉我一个更好的方法来做到这一点!
First, let's see what scenarios we have:首先,让我们看看我们有哪些场景:
When you add an "addCatch" in your state machine, the default behavior it's the error output to overwrite the step input.当您在 state 机器中添加“addCatch”时,默认行为是错误 output 以覆盖步进输入。 To solve this you only need to change the addCatch resultPath, this way you will store the error output alongside the step input.
要解决此问题,您只需更改 addCatch resultPath,这样您将在 step 输入旁边存储错误 output。
EX: "Catch": [ { "ErrorEquals": [ "States.All" ], "Next": "ErrorHandler" "ResultPath": "$.error-info" } ] EX:“Catch”:[{“ErrorEquals”:[“States.All”],“Next”:“ErrorHandler”“ResultPath”:“$.error-info”}]
const job1 = new tasks.LambdaInvoke(scope, 'First Job -- PASS', {
lambdaFunction: function1,
outputPath: '$.Payload'
})
const job2 = new tasks.LambdaInvoke(scope, 'Second Job -- PASS', {
lambdaFunction: function2,
outputPath: '$.Payload'
})
const job3 = new tasks.LambdaInvoke(scope, 'Third Job -- PASS', {
lambdaFunction: function3,
outputPath: '$.Payload'
})
const generateHandleErrorJob = () => new tasks.LambdaInvoke(scope, `Handle Error Job ${Math.random() * 160000000}`, {
lambdaFunction: functionError,
outputPath: '$.Payload'
})
const jobToThrowError = new tasks.LambdaInvoke(scope, 'Job To Throw Error -- PASS', {
lambdaFunction: fucntionThrowError,
outputPath: '$.Payload',
})
const generatePassCheckSetep = (stepName: string) => new sfn.Pass(scope, `Pass: ${stepName}`, {
resultPath: '$.step-info',
result: sfn.Result.fromObject({
step: stepName
})
})
const definition = new sfn.Parallel(scope, 'Parallel Execution -- PASS')
.branch(generatePassCheckSetep('job1').next(job1.addCatch(generateHandleErrorJob(), {resultPath: '$.error-info'})))
.branch(generatePassCheckSetep('jobToThrowError').next(jobToThrowError.addCatch(generateHandleErrorJob(), {resultPath: '$.error-info'})))
.branch(generatePassCheckSetep('job2').next(job2.addCatch(generateHandleErrorJob(), {resultPath: '$.error-info'})))
.next(job3)
new sfn.StateMachine(scope, id, {
definition,
timeout: cdk.Duration.minutes(3)
})
this.definition = new ParallelStateMachineCatch(this,
}, handleErrorFunction)
.branchCatch(job1)
.branchCatch(job2)
.branchCatch(job3)
.branchCatch(job4)
.branchCatch(job5)
.branchCatch(job6)
.next(final)
} }
Here's the ParallelStateMachineCatch code:这是 ParallelStateMachineCatch 代码:
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
})
})
}
}
Anyway, I hope I can help someone with this, that's how I managed to solve this issue.无论如何,我希望我能帮助别人,这就是我设法解决这个问题的方法。 Please, feel free to teach me better ways!
请随时教我更好的方法! Tks Good Luck and Good Code
Tks 好运和好代码
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.