Stepで覚えるStepFunctions基本のキ

2019.05.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

瀬田@大阪オフィスです。StepFunctions使ってますか?最初に想像していたよりめっちゃ便利&簡単なんで基本をご紹介したい欲。

今回の構成

こんな感じのやつを作ってみます。

テスト用lambda関数

Pythonで以下のようなlambda関数:testを作成します。

def lambda_handler(event, context):
    event["Result"] = True #項目はeventに任意に追加可能です。
    event["LoopCount"] = 10 
    return event

ステートマシン定義

Step1:Exec lambdaの実行

lambdaを実行するStepを作成します。 コメント部は空白を含めて削除してください。(行末に空白があるとエラーになります。) lambdaのarnは適宜書き換えてください。

{
  "Comment": "",       #自由書式のコメント
  "StartAt": "Exec",     #開始点
  "States": {
    "Exec": {         #Stepの動作定義開始
      "Comment": "実行",   #自由書式のコメント
      "Type": "Task",     #実行タイプ
      "InputPath":"$",    #StepFunctionを起動した時に取得した引数(CloudWatchEvents等から渡せる)
      "Resource":
      "arn:aws:lambda:ap-northeast-1:99999999999:function:test", #実行するリソースARN。InputPathの引数はlambda内のeventで取得可能。
      "ResultPath":"$",    #実行したソースからの戻り値を次の処理に渡す。
      "End": true
    }
  }
}

これを入力すると以下して、ステートマシン表示部のリロードボタンを押すと、以下のようになります。

Step2:ErrorCheck 結果の受け取りと分岐

前段の結果を受け取り、処理を分岐します。分岐先は両方とりあえず、最後の結果送信処理へ流します。lambdaからの返り値は$に入っています。

{
  "Comment": "",
  "StartAt": "Exec",
  "States": {
    "Exec": {
      "Comment": "実行",
      "Type": "Task",
      "InputPath":"$",
      "Resource":
      "arn:aws:lambda:ap-northeast-1:99999999999:function:test",
      "ResultPath":"$",
      "Next": "ErrorCheck"
      #"End": true削除
    }, #,追記
#----STEP追記----
    "ErrorCheck": {        #Stepの名称 前段の出力結果で分岐処理
      "Type" : "Choice",   #分岐処理
      "Choices": [
        {
          "Variable": "$.Result", #前Stepの処理結果が$に渡っているので、自分で定義した$.Resultを確認
          "BooleanEquals": true,  #条件判定
          "Next": "SendResult"   #次のStep名
        },
        {
          "Variable": "$.Result", #同上
          "BooleanEquals": false,
          "Next": "SendResult"
        }
      ],
      "Default": "SendResult" #条件一致しない場合の遷移先Step
    },
#----STEP追記----
    "SendResult": {   #Stepの名称 最後に実行する処理を定義
      "Type": "Task",
      "Resource":
      "arn:aws:lambda:ap-northeast-1:9999999999:function:test",
      "InputPath": "$",
      "End": true
    }
  }
}

こんな感じ。

Step3:StateCheck 状態チェックとループ

前段の結果を受け取り、対象の状態がTrueになるまで待機させます。

{
  "Comment": "",
  "StartAt": "Exec",
  "States": {
    "Exec": {
      "Comment": "実行",
      "Type": "Task",
      "InputPath":"$",
      "Resource":
      "arn:aws:lambda:ap-northeast-1:99999999999:function:test",
      "ResultPath":"$",
      "Next": "ErrorCheck"
    },
    "ErrorCheck": {
      "Type" : "Choice",
      "Choices": [
        {
          "Variable": "$.Result",
          "BooleanEquals": true,
          "Next": "StateCheck"    #実行チェックに成功したらStepステータスチェックに移行
        },
        {
          "Variable": "$.Result",
          "BooleanEquals": false,
          "Next": "SendResult"     #実行チェックに失敗したらエラーとして処理終了
        }
      ],
      "Default": "SendResult"
    },
    "SendResult": {
      "Type": "Task",
      "Resource":
      "arn:aws:lambda:ap-northeast-1:9999999999:function:test",
      "InputPath": "$",
      "End": true
    }, #,追記
#----STEP追記----
      "StateCheck": {    #Step:ステータスチェック
      "Type": "Task",
      "InputPath":"$", #前段の返り値受け取り
      "Resource":
      "arn:aws:lambda:ap-northeast-1:9999999999:function:test",
      "ResultPath":"$", #実行したソースからの戻り値を次の処理に渡す。
      "Next": "Loop"  #lambdaのチェック結果を取得して、Step:Loopに移行
    },
#----STEP追記----
    "Loop": {      #Step:Loop処理
            "Type": "Choice",
            "Choices": [{
                "Or":[{    #Loopを抜ける判定をORでしてみる。
                      "Variable": "$.Result", #前段の出力がTrueだったら、
                      "BooleanEquals": true
                      },{
                       "Variable": "$.LoopCount", #またはループ回数が10回以上であれば
                       "NumericGreaterThanEquals": 10
                    }],
                    "Next": "SendResult" #上記条件を満たした時の遷移先Step
            }],
            "Default": "Wait"  #条件を満たさなければStep:Waitへ遷移
     },
#----STEP追記----
     "Wait": {        #Step:待機処理 60秒スリープ
            "Type": "Wait", 
            "Seconds": 60,
            "Next": "StateCheck"
      } 
  }
}

以下のようになり、完成しました。

実行

実行してみると、動いてますね。

以下がそのまま貼り付けて動くコードです。(lambdaのARNは変更してください。)

{
  "Comment": "",
  "StartAt": "Exec",
  "States": {
    "Exec": {
      "Comment": "実行",
      "Type": "Task",
      "InputPath":"$",
      "Resource":
      "arn:aws:lambda:ap-northeast-1:99999999:function:test",
      "ResultPath":"$",
      "Next": "ErrorCheck"
    },
    "ErrorCheck": {
      "Type" : "Choice",
      "Choices": [
        {
          "Variable": "$.Result",
          "BooleanEquals": true,
          "Next": "StateCheck"
        },
        {
          "Variable": "$.Result",
          "BooleanEquals": false,
          "Next": "SendResult"
        }
      ],
      "Default": "SendResult"
    },
    "SendResult": {
      "Type": "Task",
      "Resource":
      "arn:aws:lambda:ap-northeast-1:99999999:function:test",
      "InputPath": "$",
      "End": true
    },
      "StateCheck": {
      "Type": "Task",
      "InputPath":"$",
      "Resource":
      "arn:aws:lambda:ap-northeast-1:99999999:function:test",
      "ResultPath":"$",
      "Next": "Loop"
    },
    "Loop": {
            "Type": "Choice",
            "Choices": [{
                "Or":[{
                      "Variable": "$.Result",
                      "BooleanEquals": true
                      },{
                       "Variable": "$.LoopCount",
                       "NumericGreaterThanEquals": 10
                    }],
                    "Next": "SendResult"
            }],
            "Default": "Wait"
     },
     "Wait": {
            "Type": "Wait", 
            "Seconds": 60,
            "Next": "StateCheck"
      } 
  }
}

最後に

lambdaで処理遷移を考えることを思えば格段に楽チンですね。GUIでシュシュっと作れたらもっと楽しくなると思うのでアップデートに期待しています。