{Step Functions}サーバーレスアプリケーションでエラーに対処する

 

https://dev.classmethod.jp/articles/lets-start-aws-step-functions-from-10min-tutorial/
https://aws.amazon.com/jp/getting-started/hands-on/handle-serverless-application-errors-step-functions-lambda/

 

-- 1. コマンド等のインストール

-- 1.1 aws cli version 2 インストール

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws --version


-- 1.2 jqインストール
sudo yum -y install jq


-- 2. IAMロール作成(Lambda用)
vim role01.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}


aws iam create-role \
--role-name role01 \
--assume-role-policy-document file://role01.json

-- 3. ポリシーをロールにアタッチ(Lambda用)
aws iam attach-role-policy \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole \
--role-name role01

 


-- 4. Lambda関数作成

vim test.py

class TooManyRequestsException(Exception): pass
class ServerUnavailableException(Exception): pass
class UnknownException(Exception): pass

def lambda_handler(event, context):
    statuscode = event["statuscode"]    
    if statuscode == "429":
        raise TooManyRequestsException('429 Too Many Requests')
    elif statuscode == "503":
        raise ServerUnavailableException('503 Server Unavailable')
    elif statuscode == "200":
        return '200 OK'
    else:
        raise UnknownException('Unknown error')


chmod 755 test.py
zip test.zip test.py


aws lambda create-function \
--function-name func01 \
--zip-file fileb://test.zip \
--handler test.lambda_handler \
--runtime python3.9 \
--role arn:aws:iam::999999999999:role/role01

 

aws lambda list-functions | grep func01
aws lambda get-function --function-name func01


-- 5. IAMポリシー作成(Step Functions用)
vim policy02.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

aws iam create-policy \
--policy-name policy02 \
--policy-document file://policy02.json

-- 6. IAMロール作成(Step Functions用)
vim role02.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "Service": "states.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}


aws iam create-role \
--role-name role02 \
--assume-role-policy-document file://role02.json

-- 7. ポリシーをロールにアタッチ(Step Functions用)
aws iam attach-role-policy \
--policy-arn arn:aws:iam::999999999999:policy/policy02 \
--role-name role02

 


-- 8. Step Functionsのステートマシンを作成する

vim sf01.json

{
  "Comment": "An example of using retry and catch to handle API responses",
  "StartAt": "Call API",
  "States": {
    "Call API": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:999999999999:function:func01",
      "Next" : "OK",
      "Comment": "Catch a 429 (Too many requests) API exception, and resubmit the failed request in a rate-limiting fashion.",
      "Retry" : [ {
        "ErrorEquals": [ "TooManyRequestsException" ],
        "IntervalSeconds": 1,
        "MaxAttempts": 2
      } ],
      "Catch": [ 
        {
          "ErrorEquals": ["TooManyRequestsException"],
          "Next": "Wait and Try Later"
        }, {
          "ErrorEquals": ["ServerUnavailableException"],
          "Next": "Server Unavailable"
        }, {
          "ErrorEquals": ["States.ALL"],
          "Next": "Catch All"
        }
      ]
    },
    "Wait and Try Later": {
      "Type": "Wait",
      "Seconds" : 1,
      "Next" : "Change to 200"
    },
    "Server Unavailable": {
      "Type": "Fail",
      "Error":"ServerUnavailable",
      "Cause": "The server is currently unable to handle the request."
    },
    "Catch All": {
      "Type": "Fail",
      "Cause": "Unknown error!",
      "Error": "An error of unknown type occurred"
    },
    "Change to 200": {
      "Type": "Pass",
      "Result": {"statuscode" :"200"} ,
      "Next": "Call API"
    },
    "OK": {
      "Type": "Pass",
      "Result": "The request has succeeded.",
      "End": true
    }
  }
}

aws stepfunctions create-state-machine \
--name sf01 \
--definition file://sf01.json \
--role-arn arn:aws:iam::999999999999:role/role02 \
--type STANDARD

aws stepfunctions list-state-machines

aws stepfunctions describe-state-machine \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01


-- 9. ステートマシンのテスト


aws stepfunctions start-execution \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01 \
--name test11 \
--input '{
    "statuscode": "200"
}'


aws stepfunctions list-executions \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01

aws stepfunctions describe-execution \
--execution-arn arn:aws:states:ap-northeast-1:999999999999:execution:sf01:test11


aws stepfunctions start-execution \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01 \
--name test12 \
--input '{
    "statuscode": "503"
}'


aws stepfunctions list-executions \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01

aws stepfunctions describe-execution \
--execution-arn arn:aws:states:ap-northeast-1:999999999999:execution:sf01:test12

 

aws stepfunctions start-execution \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01 \
--name test13 \
--input '{
    "statuscode": "429"
}'


aws stepfunctions list-executions \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01

aws stepfunctions describe-execution \
--execution-arn arn:aws:states:ap-northeast-1:999999999999:execution:sf01:test13

 

aws stepfunctions start-execution \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01 \
--name test14 \
--input '{
    "statuscode": "999"
}'


aws stepfunctions list-executions \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01

aws stepfunctions describe-execution \
--execution-arn arn:aws:states:ap-northeast-1:999999999999:execution:sf01:test14

 


-- 10. クリーンアップ

-- ステートマシンの削除

 

aws stepfunctions list-state-machines

aws stepfunctions describe-state-machine \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01

aws stepfunctions delete-state-machine \
--state-machine-arn arn:aws:states:ap-northeast-1:999999999999:stateMachine:sf01

 


-- IAMロールの削除(Step Functions用)
aws iam list-roles | grep role02

aws iam detach-role-policy \
--role-name role02 \
--policy-arn arn:aws:iam::999999999999:policy/policy02

aws iam delete-role --role-name role02


-- IAMポリシーの削除(Step Functions用)
aws iam list-policies | grep policy02

aws iam delete-policy \
--policy-arn arn:aws:iam::999999999999:policy/policy02


-- Lambda関数の削除

aws lambda get-function --function-name func01
aws lambda delete-function --function-name func01


-- IAMロールの削除(Lambda用)
aws iam list-roles | grep role01

aws iam detach-role-policy \
--role-name role01 \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

aws iam delete-role --role-name role01