In addition to dealing with temporary problems with Retry, Step Functions also allows us to catch specific errors and respond by transitioning to the appropriate states to handle these errors.
For example, let’s say that there are some types of names that our data checking service cannot handle. In these cases, instead of flagging the application for review, we will flag the application as unprocessable due to incompatible data.
To illustrate this possibility, we’ll leverage some of the testing code in the Lambda function Data Checking to tell it to throw an error if it sees a specific string of characters passing in the poster’s name. sign.
We’ll update our state machine to detect this specific type of custom error and redirect to the new state, and flag the application as unprocessable.
In this step we will:
Add a new state Flag Application As Unprocessable to the state machine.
Add Catch configuration to Check Name state in our state machine, if encountering data that cannot be processed, it will switch to Flag Application As Unprocessable state.
{
"StartAt": "Check Name",
"States": {
"Check Name": {
"Type": "Task",
"Parameters": {
"command": "CHECK_NAME",
"data": {
"name.$": "$.application.name"
}
},
"Resource": "${DataCheckingFunctionArn}",
"ResultPath": "$.checks.name",
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
]
}
],
"Catch": [
{
"ErrorEquals": [
"UnprocessableDataException"
],
"ResultPath": "$.error-info",
"Next": "Flag Application As Unprocessable"
}
],
"Next": "Check Address"
},
"Check Address": {
"Type": "Task",
"Parameters": {
"command": "CHECK_ADDRESS",
"data": {
"address.$": "$.application.address"
}
},
"Resource": "${DataCheckingFunctionArn}",
"ResultPath": "$.checks.address",
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
]
}
],
"Next": "Review Required?"
},
"Review Required?": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.checks.name.flagged",
"BooleanEquals": true,
"Next": "Pending Review"
},
{
"Variable": "$.checks.address.flagged",
"BooleanEquals": true,
"Next": "Pending Review"
}
],
"Default": "Approve Application"
},
"Pending Review": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "${FlagApplicationFunctionName}",
"Payload": {
"id.$": "$.application.id",
"flagType": "REVIEW",
"taskToken.$": "$$.Task.Token"
}
},
"ResultPath": "$.review",
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
]
}
],
"Next": "Review Approved?"
},
"Review Approved?": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.review.decision",
"StringEquals": "APPROVE",
"Next": "Approve Application"
},
{
"Variable": "$.review.decision",
"StringEquals": "REJECT",
"Next": "Reject Application"
}
]
},
"Reject Application": {
"Type": "Task",
"Parameters": {
"id.$": "$.application.id"
},
"Resource": "${RejectApplicationFunctionArn}",
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
]
}
],
"End": true
},
"Approve Application": {
"Type": "Task",
"Parameters": {
"id.$": "$.application.id"
},
"Resource": "${ApproveApplicationFunctionArn}",
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
]
}
],
"End": true
},
"Flag Application As Unprocessable": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "${FlagApplicationFunctionName}",
"Payload": {
"id.$": "$.application.id",
"flagType": "UNPROCESSABLE_DATA",
"errorInfo.$": "$.error-info"
}
},
"ResultPath": "$.review",
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
]
}
],
"End": true
}
}
}
sam deploy
aws lambda invoke --function-name sfn-workshop-SubmitApplication --payload '{ "name": "UNPROCESSABLE_DATA", "address": "123 Street" }' /dev/stdout
aws lambda invoke --function-name sfn-workshop-FindApplications --payload '{ "state": "FLAGGED_WITH_UNPROCESSABLE_DATA" }' /dev/stdout