LoginSignup
10
11

More than 5 years have passed since last update.

AWS Step FunctionsでStateMachineを書いてみる

Last updated at Posted at 2016-12-10

俺メモ
こんな記事を見るよりこっちを読んだ方が100倍わかりやすいです。

StepFunctions

AWS re:Invent2016 にてStepFunctionsがリリースされました。
状態マシンを書いてLambdaの処理をさせることができるサービスです。
とりあえず書きかたをメモっておきましょうか。

シンプルなStepFunctions

JSON
{
  "Comment": "ここにコメントを入れる",
  "StartAt": "開始関数の名前をここに入れる",
  "States": { // 関数の定義一覧をここに書く
    "HelloWorld": { // 関数名
      "Type": "Task", // 関数のタイプ。TaskはLambdaの処理が入る
      "Resource": "LambdaのARNを入れる",
      // End: trueを指定すると、この処理が終わったら状態マシン終了。
      "End": true, // この処理が終わったら状態マシン終了。
      // Next: "hoge"を指定すると、この処理が終わったら、次にhogeを実行する。
      "Next": "hoge"
    }
  }
}

2016-12-13_12h17_08.png

Type

Task

LambdaのARNが指定できる。

JSON
"HelloWorld": {
  "Type": "Task",
  "Resource": "LambdaのARN",
  "End": true
}

2016-12-13_12h17_27.png

Wait

指定した秒数とか(いろいろ指定できる)待たせることができる。

JSON
"WaitWorld": {
  "Type": "Wait",
  // 待つ秒数の指定には様々な方法がある。
  // 以下のいずれかを指定する。
  "Seconds": 10, // 10秒待つ。
  "Timestamp": "2015-09-04T01:59:00Z" // 指定したTimeStampまで待つ(そんなん使うんか?)
  "SecondsPath": "$.hogeTimestamp", // 変数が使える(後述)
  "TimestampPath": "$.hogeSeconds" // 変数が使える
}

Choice

前段の処理結果によって後続の処理を分岐する

JSON
"ChoiceWorld": {
  "Type": "Choice",
  "Choices": [ {
    // 前段の処理で帰ってくるパラメータは $ に入っている。
    // $がオブジェクトとしたとき、$.response_cdの中の値をチェックする
    "Variable": "$.response_cd",
    // response_cdの値が"1"であるなら、NextWorldを実行する。
    "StringEquals": "1",
    "Next": "NextWorld1"
  }, {
    "Variable": "$.response_cd",
    "StringEquals": "2",
    "Next": "NextWorld2"
  } ],
  "Default": "NextWorld3"
}
前段処理のjavascript
exports.handler = function(event, context, callback) {
  // 
  callback( null, {
    "response_cd": "1"
  } );
};

2016-12-13_12h40_13.png

Parallel

並列処理を行います。
Branchesで配列を設定でき、Branchesの配列一つ一つには、さらに新規にStepFunctionsの処理を書くことができます。

JSON
"ParallelWorld": {
  "Type": "Parallel",
  "Next": "NextWorld",
  // Branchesの中身は、一般的なStep Functionsと同じ。(Step Functionsの中にStep Functionsを定義するようなイメージ)
  "Branches": [ {
    "StartAt": "World1",
    "States": {
      "World1": {
        "Type": "Task",
        "Resource": "ARN",
        "End": true
      }
    }
  }, {
    "StartAt": "World2-1",
    "States": {
      "World2-1": {
        "Type": "Task",
        "Resource": "ARN",
        "Next": "World2-2"
      },
      "World2-2": {
        "Type": "Task",
        "Resource": "ARN",
        "End": true
      }
    }
  } ]
}

2016-12-13_12h29_56.png

変数について

前段から返却されたパラメータについては、$を使ってアクセスすることができます。
たとえば、以下のようなコードで値を返した場合、

前段のコード
exports.handler = function(event, context, callback) {
  callback( null, {
    "response": 20
  } );
};

変数として、$でアクセスすることができます。
例えばWaitのSecondPathの場合、

JSON
"WaitWorld": {
  "Type": "Wait",
  "SecondPath": "$.response"
  "Next": "NextWorld"
}

$.responseで秒数を取得できます。
オブジェクトではなく、文字列などを返却した場合は$でその文字列にアクセスできます。

その他

Catch

Taskが何らかのエラーで失敗した場合に、Catchハンドラで捕まえてエラー時の処理を実行させることができます。

JSON
"CatchWorld": {
  "Type": "Task",
  "Resource": "ARN",
  "Catch": [ {
    "ErrorEquals": [ "HandledError" ],
    "Next": "NextWorld"
  } ],
  "End": true
},
"NextWorld": {
  // ...
}

Retry

Catchとだいたい一緒です。
違いは、エラーになった場合に、再実行するところでしょうか。BackoffRateは何のことかわかりません。

JSON
"CatchWorld": {
  "Type": "Task",
  "Resource": "ARN",
  {
    "ErrorEquals": ["HandledError"],
    "IntervalSeconds": 1, // 再実行するときにインターバルをあける
    "MaxAttempts": 2, // 再実行回数
    "BackoffRate": 2.0
  },
  "End": true
}

試しに何か書いてみます。

{
  "Comment": "A Hello World example of the Amazon States Language using an AWS Lambda Function",
  "StartAt": "Func1",
  "States": {
    "Func1": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:***:function:stepFunction1",
      "Next": "Choice1"
    },
    "Choice1": {
      "Type": "Choice",
      "Choices": [ {
        "Variable": "$",
        "StringEquals": "Hello",
        "Next": "Func2-A"
      }, {
        "Variable": "$",
        "StringEquals": "Bye",
        "Next": "Func2-B"
      } ]
    },
    "Func2-A": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:***:function:stepFunction1",
      "Next": "Parallel1"
    },
    "Func2-B": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:***:function:stepFunction1",
      "Next": "Parallel1"
    },
    "Parallel1": {
      "Type": "Parallel",
      "Branches": [ {
        "StartAt": "World3-1-1",
        "States": {
          "World3-1-1": {
            "Type": "Task",
            "Resource": "arn:aws:lambda:ap-northeast-1:***:function:stepFunction1",
            "Next": "World3-1-2"
          },
          "World3-1-2": {
            "Type": "Task",
            "Resource": "arn:aws:lambda:ap-northeast-1:***:function:stepFunction1",
            "End": true
          }
        }
      }, {
        "StartAt": "World3-2",
        "States": {
          "World3-2": {
            "Type": "Task",
            "Resource": "arn:aws:lambda:ap-northeast-1:***:function:stepFunction1",
            "End": true
          }
        }
      } ],
      "Next": "World4"
    },
    "World4": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:***:function:stepFunction1",
      "End": true
    }
  }
}

2016-12-13_12h34_39.png

10
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
11