AWS Step Functions

AWSのStep Functionsについて学んだ事を纏めます。

#1 Step Functionとは
ステートマシンと呼ばれるオブジェクトを作成してタスクを順次実行するサービス。
実行する処理の制御にはステートを使用する。
ステートで制御できる内容は下記のようなものがあります。
- 処理Aが成功したら処理Bを実行する。
- 処理Bが成功したら処理CとDを同時実行する。
- 処理Cの結果が1だったら処理E、0だったら処理Fを実行する。
- 処理Gのが失敗したら処理Hを実行する。
- 処理Iが成功したら一定時間処理を停止する。

このような制御フローをグラフィカルに確認しながら作成できる。

#2 実際に触ってみる
上記の説明だけでは全然ピンと来ないので実際に触ってみます。

###2.1 まずはテンプレートのHello World!
始めに、元から用意されているテンプレートのうち、Hello Worldを作成して動かしてみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/deab42f5-3f71-eb9b-33b8-fbb6488094e0.png)

テンプレートからHello Worldを選択して作成するとこのような画面が表示されました。
左側のプログラムコードは「ステートメント言語」と呼ばれるものです。
これを記述することでタスクのフローを作成していきます。
ステートメント言語の仕様は[このページ](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/concepts-amazon-states-language.html)にまとめられています。
右の図のStartとEndはそれぞれ処理の開始点と終了点です。
真ん中のHelloWorldと書かれているものは「ステート」と呼ばれるものです。
HelloWorldという名前のステートがどのような動きをするのかが左側のこの部分です。

```
    "HelloWorld": {
      "Type": "Pass",
      "Result": "Hello World!",
      "End": true
    }
```
ステートにはいくつかの種類があり、Typeで表記されます。ここではPassという種類が使われています。
Passは特に何も処理せずに次のステートに遷移します。
その際にResultに記述された内容を次のステートに渡すことができます。
今回は次のステートが終了なのでこのメッセージが最終出力として出力されます。
これはデバッグ時に処理がどこまで進んだのかを知る等の用途で使われます。
ではこのステートマシンを実行してみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/e3f1ff2b-a6ed-3c20-3059-8f4e9049801b.png)
処理が成功してHelloWorldが出力されました。

###2.2 自分でPassステートを追加してみる
HelloWorldというメッセージを出力するステートの次にHelloWorld2というメッセージを出力してみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/2f35128d-9962-4591-4965-d8b028f49cbe.png)

赤枠で囲った部分が変更した部分です。
左側のステートメント言語を追記すると右側のフロー図にも更新が入って視覚的に処理の流れを理解することができます。
これを実行するとこのようになりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/fa8820b9-c011-c99d-ba0a-4c6e41cb6638.png)
HelloWorldの後にHelloWorld2を追加したので最終的な出力はHelloWorld2になりました。

###2.3 分岐(Choice)ステートを使ってみる
次に、入力に応じて実行する処理を変更できるChoiceステートを使用してみます。
ステートマシンの記述をこのように変更しました。

```
{
  "Comment": "A Hello World example of the Amazon States Language using a Pass state",
  "StartAt": "ChoiceState",
  "States": {
    "ChoiceState": {
      "Type": "Choice",
      "Choices":[
        {
          "Variable": "$.value",
          "NumericEquals": 1,
          "Next": "HelloWorld1"
        },
        {
          "Variable": "$.value",
          "NumericEquals": 2,
          "Next": "HelloWorld2"
        }
      ],
    "Default":"HelloWorld1"
     },
    "HelloWorld1": {
      "Type": "Pass",
      "Result": "Hello World1!",
      "End": true
    },
      "HelloWorld2": {
      "Type": "Pass",
      "Result": "Hello World2!",
      "End": true
    }
  }
}
```
フロー図はこんな感じです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/905496a1-70d3-2ddc-4021-fd7d718eca70.png)
今回は入力値"value"が2だったらhelloWorld2、1、もしくはその他だったらHelloWorldを実行するようにしています。
Defaultでステートを指定することで条件に一致しなかった場合の処理を定義できます。

これを実行します。
入力のvalueに2を設定してみます。
入力値はこのように実行時にJSON形式で指定できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/08cf7f84-ed72-375d-6eb2-5262a0965fb4.png)

結果はこのようになりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/96eb16a6-c8a3-67bd-2ceb-058056aadb22.png)
緑色になっているのが通ったステートです。
HelloWorld2が緑色になっているので想定通りに処理を分岐できていることが分かります。

###2.4 例外発生時の処理を書いてみる
次は処理を失敗させるステート(Fail)を使ってみます。

ステートマシンの記述をこのように変更しました。

```
{
  "Comment": "A Hello World example of the Amazon States Language using a Pass state",
  "StartAt": "ChoiceState",
  "States": {
    "ChoiceState": {
      "Type": "Choice",
      "Choices":[
        {
          "Variable": "$.value",
          "NumericEquals": 1,
          "Next": "HelloWorld1"
        },
        {
          "Variable": "$.value",
          "NumericEquals": 2,
          "Next": "FailState"
        }
      ],
    "Default":"HelloWorld1"
     },
    "HelloWorld1": {
      "Type": "Pass",
      "Result": "Hello World1!",
      "End": true
    },
      "FailState":{
      "Type":"Fail",
      "Cause":"input value not found",
       "Error":"HelloError"
    }
  }
}
```


フロー図はこんな感じです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/721d4f3a-242a-6981-c6e3-3c3d252a828a.png)

実行してみます。
Choiceの入力(value)は2を設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/7a9b3445-2c7c-6a6c-84e9-bbecdfb188a7.png)
実行ステータスが「失敗」になっていることが確認できます。
Failの他に必ず処理を成功で終了させる「Sucess」というステートもあります。

###2.5 並列処理を書いてみる
次に、並列処理(Parallel)を使ってみます。

ステートメントマシンをこのように記述しました。

```
{
  "Comment": "A Hello World example of the Amazon States Language using a Pass state",
  "StartAt": "ParallelState",
  "States": {
    "ParallelState": {
      "Type": "Parallel",
      "End":true,
      "Branches":[
        {
          "StartAt":"HelloWorld1",
          "States":{
            "HelloWorld1": {
            "Type": "Pass",
            "Result": "Hello World1!",
            "End": true
            }
          }
        },
        {
         "StartAt":"HelloWorld2",
          "States":{
            "HelloWorld2": {
            "Type": "Pass",
            "Result": "Hello World2!",
            "End": true
            }
          }
        }
      ]
     }
  }
}

```
フロー図はこんな感じです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/a4f53fd5-9e4a-f83f-f9dd-94ea098c7dd4.png)

実行してみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/162114/1ecdf379-f643-6c04-7a74-c13cb3e3d55f.png)
HelloWorld1とHelloWorld2の両方が緑色になっていて出力も両方出ているのでどちらも並列に実行されていることが分かります。

#3. ステートについてまとめ
ステートについて改めて制御内容をまとめてみます。
上記で触れなかったステートでWaitとTaskについても紹介します。

|ステート|制御内容|
|:--:|:--:|
|Pass|何もしない。処理をそのまま続行する|
|Choice|入力された条件に応じて次に実行する処理を変更する|
|Parallel|処理を並行して実行する|
|Fail|ステートマシンの処理を失敗で終わらせる|
|Success|ステートマシンの処理を成功で終わらせる|
|Wait|処理を一定時間停止する|

#4. Taskについて
ここまで紹介したステートは処理の流れを制御するものです。
これに対して実行したい処理の本体はTaskと呼ばれるステートで記述します。
(つまりTaskもステートの一種です。)
このTaskはアクティビティとLambda関数に分類できます。

- アクティビティ  
任意のプログラムコード。
- Lambda関数  
AWS Lambdaで作成した関数

#5. まとめ  
 
- StepFunctionとは任意のプログラムコード、もしくはLambda関数をステートと呼ばれるオブジェクトを使用して制御(分岐・並列処理等)できるものである。
- ステートによって構成されたオブジェクトをステートマシンという。
- ステートマシンをグラフィカルに確認することができる。