初めてのAWS Step Functions

# Step Functions
## Step Functionsとは
- 視覚的なワークフローを使用して、AWSの分散アプリケーションとマイクロサービスのコンポーネントを調整できるウェブサービス
- Step Functionsを使用して構築するワークフローはステートマシンと呼ばれ、ワークフローの各ステップはステートと呼ばれる
- Step Functionsは、以前ステートの出力が現ステートの入力となるようにワークフローを設計・実行でき、作業を手軽に調整できる完全管理型サービスである

### Step Functionsの特徴
#### ワークフローの構成と抽象化
ワークフローをステートマシンとして定義し、複雑なコードを理解しやすいステートメントとダイアグラムに変換
視覚的に分かりやすい構成により、アプリケーションの構築やそれらが望ましい機能を実装していることの確認が簡単に出来る
また、アプリケーションの実装からロジックを分離したから、ロジックを変更する必要なくステップを再構成出来る

#### AWSサービスの利用
他のAWSのサービスを呼び出してワークフローを設定可能
参照：[AWS Step Functions Use Cases](https://aws.amazon.com/jp/step-functions/use-cases/)
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/5d8561fb-1d22-ad87-9321-8d3bbbfe017f.png)

すでに使用しているサービスを統合してアプリケーションを構築し、新たな構成にすばやく書き換えることができる

- コンピューティングサービス (AWS Lambda、Amazon ECS、AWS Fargate)
- データベースサービス (Amazon DynamoDB)
- メッセージングサービス (Amazon SNS と Amazon SQS)
- データ処理サービス (AWS Batch と AWS Glue、Amazon EMR)
- 機械学習サービス (Amazon SageMaker)

また、すでに使用しているアプリケーションコンポーネントを統合して新たなアプリケーションを構築することもできる

#### ステート

**ステート**と呼ばれる、ワークフロー用に事前作成されたステップを提供
ステートはベーシックサービスプリミティブを実装するため、アプリケーションからロジックを取り除くことができる
また、ワークフロー各ステップのステート管理により、新たにステート管理を構築する必要なし

##### サービスプリミティブとは
OSI参照モデルにてサービス利用時の階層間の通信信号

**System AからSystem Bへ通信要求時の図**
参照：[Service Primitives](https://erg.abdn.ac.uk/users/gorry/course/intro-pages/service-prim.html)
![service_primitive.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/7e14b03f-7a0a-9ce6-1213-d5a96f6239d2.png)

**サービスプリミティブの信号**

| 種類 | 役割 | 通信方向 | 詳細 | 例（電話） |
|:-:|:-:|:-:|:-:|:-:|
| Request | サービス利用 | 上位→下位 | サービスの開始要求 |　発信者が電話番号を押す |
| Indication | サービス提供 | 下位→上位 | サービスの開始表示 | 該当番号の端末のベールがなる |
| Response | サービス利用 | 上位→下位 | Indicationによるサービス実行表示 | 受信者が通話ボタン押下 |
| Confirm | サービス提供 | 下位→上位 | Responseによるサービスん実行表示 | 発信音が終わり、電話がつながる |


#### その他
- 各実行の履歴（すべての実行をログに記録）
- 視覚的なモニタリング（ボタン押下で起動、起動後のステップや結果は視覚的に確認可能）
- エラーや例外は組み込まれたtry/catch および retry により自動で処理される
- 自動スケーリング
- 利用に応じた支払い
- 大容量オーケストレーション by Express Workflow
- VPC エンドポイント(VPCE) のサポートによるセキュリティー
- 今も追加されつつある

## 詳細
### 標準・Expressワークフロー
[標準ワークフローとExpress ワークフロー](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/concepts-standard-vs-express.html)

ステートマシンを作成するときは、標準または Express のいずれかを選択必要
ステートマシンが作成された後は、**タイプ変更不可**
選択したタイプによってステートマシンの実行時の動作が異なる

| 比較項目 | 標準ワークフロー | Expressワークフロー |
|:-:|:-:|:-:|
| 適切な作業 | **長時間実行され、耐久性が高く、監査可能なワークフロー** | **大容量のイベント処理ワークロード** **(1)** |
| 例 | 機械学習モデルのトレーニング、<br />レポート生成、<br />IT の自動化、<br />注文処理など | IoT データの取り込み、<br />ストリーミングデータの処理と変換、<br />大量のマイクロサービスオーケストレーションなど |
| 最大期間 **(2)** | 1年 | 5分 |
| 最大実行アイドル時間（最大遊休時間）| 1年 | 5分 |
| サポートされている実行開始レート | 毎秒 2,000 以上 | 毎秒 100,000 以上 |
| サポートされている状態遷移レート | 1アカウント・1秒あたり 4,000 以上 | 無制限 |
| 価格設定 **(3)** | 状態移行 **(4)**ごとの価格設定 | 実行回数、実行時間、およびメモリ消費量によって価格設定 |
| 実行履歴 | **Step FunctionsのAPIを使って一覧表示・記述可能<br />コンソールから視覚的にデバッグ可能**<br />ステートマシンでのロギングを有効にしてCloudWatch Logsで実行検査可能 | ステートマシンでのロギングを有効してCloudWatch Logsで実行検査可能 |
| 実行履歴の最大サイズ | 25,000イベント **(5)** | 無制限 |
| 実行履歴の最大保持期間 | 90日間（追加不可） | 15ヶ月間（CloudWatchのログ保存期間） |
| 実行セマンティクス **(6)** | 1回だけワークフロー実行 | 最低1回ワークフロー実行 |
| サービス統合 **(7)** | すべてのサービス統合とパターンをサポート | すべてのサービス統合をサポート<br />ジョブ実行 (.sync) パターン・コールバック (.waitForTaskToken) パターン除外 |
| アクティビティサポート **(8)** | する | しない |

※ 上記の[各種制限（クォータ）](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/limits-overview.html)はサポートセンターにて引き上げリクエスト可能

* (1) 大容量のイベント処理ワークロードの例：IoT データの取り込み、ストリーミングデータ処理と変換、モバイルアプリケーションのバックエンドなど
* (2) 最大期間：各ワークフローが最大時間を超える場合、States.Timeout エラーで失敗し、ExecutionsTimedOut CloudWatch メトリクスを出力。
* (3) 価格設定：下記の料金体系を参照
* (4) 状態遷移：実行のステップが完了するたびにカウントされる
* (5) 実行履歴の最大サイズ制限：実行履歴が最大サイス（25,000件）達すると実行は失敗。これを回避するために、AWS Lambda関数を使用して[新しい実行として続行](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/tutorial-continue-new.html)
* (6) 実行セマンティクス：ワークフローの重複実行可否（[最低 1 回のワークフロー実行](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/express-at-least-once-execution.html)）
* (7) サービス統合：AWS Step Functionsは一部のAWSサービスを統合するため、API アクションを呼び出し、Step Functions内でAmazonステートメント言語から実行を直接調整可能。詳細は下記サービス統合を参照
* (8) アクティビティサポート：[アクティビティ](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/concepts-activities.html)

### 状態（States）
[状態（States）](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/concepts-states.html)

Step Functionsはステートマシンの概念を基盤としていて、JSON基盤のAmazon States言語でステートマシンを定義する
Step Functionsコンソールでは、アプリケーションロジックを視覚化するため、そのステートマシンをグラフィカルに表示する

状態はステートマシンの要素で、名前で参照される
任意の文字列を指定できるが、ステートマシン全体の範囲で一意である必要がある

#### 状態（States）の種類

| 状態 | 詳細 |
|:-:|:-:|
| Task | ステートマシンで何らかの作業をする |
| Choice | 実行の選択肢間で選択する |
| Fail/Succeed | 失敗または成功で実行を停止する |
| Pass | 入力を出力に渡す<br />（単純に渡す or 一部修正されたデータを渡す） |
| Wait | 一定時間または指定された時刻/日付まで実行を遅延する |
| Parallel | ブランチの並列実行を開始する |
| Map | 動的にステップを反復する |

Step Functionsのワークフロー上の各ステップ（State）に、上記の状態がTypeとして定義される
- 各状態には、必ずその状態のタイプを示すTypeフィールドが必要
- 各状態はCommentフィールドを持つことができ、人の目で確認できる説明を記載できる。

![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/e6278544-b7bf-aa1e-9012-4483fb61d81a.png)

#### Transitions（状態移行）
状態から状態への移行は、以下のようにフィールドで定義する

<img width="351" alt="transition.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/63503237-4a53-11c3-9ce6-c07f24b503c2.png">

状態移行用フィールド

| フィールド | 位置 | 値 | 詳細 |
|:-:|:-:|:-:|:-:|
| StartAt | システム最上位 | String | フィールドの値と一致する名前の状態を**start状態**に指定 |
| Next | 状態の中 | String | フィールドの値と一致する名前の状態を、状態の実行が終わってからの移行先として指定<br />基本はNextを通じた一つの移行ルールのみを許可するが、Choice**(1)**などの制御状態によっては複数指定可能 |
| End | end状態 | Boolean | 終了状態 |
| Type**(2)** | Succeed/Fail状態 | Succeed/Fail | 終了状

- (1) Choice状態でのNext設定
配列を使い、複数の状態をNextに指定可能

<img width="301" alt="choice.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/ae4ced99-bba2-e70b-0cd9-e70b3484217f.png">

```
{
  "Comment": "choice state.",
  "StartAt": "ChoiceState",

  "States": {
    "ChoiceState": {
      "Type" : "Choice",
      "Choices": [
        {
          "Variable": "$.foo",
          "NumericEquals": 1,
          "Next": "FirstMatchState"
        },
        {
          "Variable": "$.foo",
          "NumericEquals": 2,
          "Next": "SecondMatchState"
        }
      ],
      "Default": "DefaultState"
    },

    "FirstMatchState": {
      "Type" : "Task",
      "Resource": "FirstMatchFunction",
      "Next": "NextState"
    },

    "SecondMatchState": {
      "Type" : "Task",
      "Resource": "SecondMatchFunction",
      "Next": "NextState"
    },

    "DefaultState": {
      "Type": "Fail",
      "Error": "DefaultStateError",
      "Cause": "No Matches!"
    },

    "NextState": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
      "End": true
    }
  }
}
```

- (2) Type : Succeed/Fail
    - TypeがSucceedまたはFailの状態は、終了状態とし、EndやNextフィールドはいらない


### ステートマシン実行
以下の方法でStep Functionsの実行が可能
- [StartExecution API](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html) アクションを呼び出す
- Step Functions コンソールで実行
- [Amazon CloudWatch Events](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/tutorial-cloudwatch-events-s3.html) を使用して実行
- [Amazon API Gateway](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/tutorial-api-gateway.html) で実行
- Task 状態からネストされたワークフロー実行（ステートマシンの中でステートマシン呼び出し）

### 入力および出力処理
#### ステートマシンデータ
- ステートマシンデータはJSONテキストで表記される
- ステートマシン実行時に、初期入力データをstart状態に渡すことが可能
- 初期データ入力には、以下の二つの方法が存在
    - AWS CLIより[StartExecution](https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html) APIを呼び出す際にinputとして渡す（方法は[こちら](https://dev.classmethod.jp/articles/aws-step-functions-with-aws-cli/#toc-2-)を参照）
    - Step Functions Consoleにて、実行時に初期データを入力
- 最後の状態にて、実行の出力がJSONテキストとして返ってくる

#### JSONデータの制御
Amazon States言語では以下のフィールドで状態間のJSONデータの流れを制御

| フィールド | 詳細 |
|:-:|:-:|
| InputPath | 初期入力データの中で、状態のInputとして使うデータを指定 |
| Parameters | Key-Valueペアの集合を作成<br />（JSONの組み立て可能） |
| ItemsPath | 配列データを指定<br />Map状態で使用 |
| ResultPath | 状態が出力する結果を指定<br />未指定し、基本値の**$**が設定、すべての作業結果を返却<br />**null**を入力時、Inputをそのまま出力 |
| OutputPath | 次の状態へ渡すデータを指定<br />未指定し、基本値の**$**が設定、全体のJSONノードを次の状態へ渡す |

#### データ制御の実行例
Step Functionsで初期データを入れ、Lambda関数を通した結果を出力

##### Lambda
以下のFunctionを作成

```
exports.handler = (event, context, callback) => {
    callback(null, "Hello, " + event.who + "!");
};
```

##### Step Functions
以下のワークフローを作成

<img width="472" alt="input-outut-expl.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/803accf2-233a-57ad-a5be-75ff5d3a5e86.png">

```
{
  "Comment": "A Hello World example of the Amazon States Language using an AWS Lambda function",
  "StartAt": "HelloWorld",
  "States": {
    "HelloWorld": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:656378142995:function:HelloFunction",
      "InputPath": "$.lambda",
      "ResultPath": "$.data.lambdaresult",
      "OutputPath": "$.data",
      "End": true
    }
  }
}
```

##### 入力データ
以下のデータを準備

```
{
  "comment": "An input comment.",
  "data": {
    "val1": 23,
    "val2": 17
  },
  "extra": "foo",
  "lambda": {
    "who": "AWS Step Functions"
  }
}
```

##### 実行
※実行時には、Step FunctionsのIAMにて**LambdaへのAccessを許可**しておくこと

<img width="960" alt="iam-lambda.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/9be0e0fa-4958-81f6-f571-3cc1cf7c3398.png">

1. 作成したState machineにて**Start execution**ボタン押下
2. New execution モーダルが開かれたら、Inputに準備したJSONデータを入れ、**Start execution**ボタン押下
3. 以下のように結果出力
<img width="751" alt="result.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/fcd4f448-92b0-8236-bd05-c2ba8910fece.png">

##### 解説
１．データ読み込み
２．StartAtで指定した、Hello World状態へ
３．Hello World状態はLambda Functionを呼び出す
４．Lambda Functionへのインプットは、InputPathにて指定した"$.lambda"のみ

```
"lambda": {
    "who": "AWS Step Functions"
}
```

５．Lambda Functionの結果は**Hello, AWS Step Functions!**
６．Lambda Functionの結果は、ResultPathにて指定した"$.data.lambdaresult"へ収納
７．"End": trueなので、State machine終了
８．終了時に出力するアウトプットは、"OutputPath"で指定した"$.data"

```
{
    "val1": 23,
    "val2": 17,
    "lambdaresult": "Hello, AWS Step Functions!"
}
```

### エラー処理
[Step Functions でのエラー処理](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/concepts-error-handling.html)

Step Functionsはエラーハンドリングが組み込まれていて、状態に関連フィールドを入れるだけでTry~Catchやエラー後の再試行までしてくれる。

#### Step Functionsのエラー名
Step Functionsは文字列を使用してAmazon States言語でエラーを識別

| エラー名 | 詳細 |
|:-:|:-:|
| States.ALL | すべての既知のエラー名に一致するワイルドカード |
| States.Runtime | 処理できなかった例外のため、実行に失敗<br/>実行時のエラーが原因の確立が高い<br />再実行せずに実行失敗となる<br />（States.ALLでの再実行でもStates.Runtimeエラーは検出されない） |
| States.Timeout | Task状態にて設定値（TimeoutSeconds, HeartbeatSeconds）より長時間機能しなかった場合 |
| States.TaskFailed | Task状態にて実行中に失敗 |
| States.Permissions | Task状態にて、必要な特権が足りないため失敗 |
| その他 | Lambdaで処理したエラーなど |


### サービス統合
[サービス統合](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/concepts-service-integrations.html)

AWS Step Functionsは一部のAWSサービスを統合するため、API アクションを呼び出し、Step Functionsの内でAmazon States言語から実行を直接調整（API にパラメータを直接呼び出し、渡すなど）することができる

#### 他サービス調整の例
- AWS Lambda 関数を呼び出す（リクエスト・レスポンス）
- AWS Batch ジョブを実行後、結果に基づき、別のアクションを実行する（ジョブ実行）
- Amazon DynamoDB に項目を挿入するか、ここから項目を取得する（リクエスト・レスポンス）
- Amazon Elastic Container Service (Amazon ECS) タスクを実行して、完了するまで待機する（ジョブ実行, コールバック待機）
- Amazon Simple Notification Service (Amazon SNS) でトピックに発行する（リクエスト・レスポンス）
- Amazon Simple Queue Service (Amazon SQS) でメッセージを送信する（リクエスト・レスポンス）
- AWS Glue または Amazon SageMakerのジョブを管理する（ジョブ実行）
- Amazon EMR ジョブを実行するためのワークフローを構築する（ジョブ実行）
- AWS Step Functions ワークフロー実行を開始する（ジョブ実行）

#### データ統合のサポート
標準ワークフローとExpressワークフローはサポートの範囲が異なる

|  | 標準ワークフロー | Express ワークフロー |
|:-:|:-:|:-:|
| リクエスト・レスポンス | 〇 | 〇 |
| ジョブ実行 (.sync) | 〇 | ✖ |
| コールバック待機 (.waitForTaskToken) | 〇 | ✖ |

##### 標準ワークフローにてサポートされるサービス統合
上記比較表にて標準ワークフローのサポート範囲は全〇だったが、サービスによってはサポートされない機能もある

| サービス | リクエスト・レスポンス | ジョブ実行 (.sync) | コールバック待機 (.waitForTaskToken) |
|:-:|:-:|:-:|:-:|
| Lambda | 〇 |   | 〇 |
| AWS Batch | 〇 | 〇 |   |
| DynamoDB | 〇 |   |   |
| Amazon ECS/AWS Fargate | 〇 | 〇 | 〇 |
| Amazon SNS | 〇 |   | 〇 |
| Amazon SQS | 〇 |   | 〇 |
| AWS Glue | 〇 | 〇 |   |
| Amazon SageMaker | 〇 | 〇 |   |
| Amazon EMR | 〇 | 〇 |   |
| Step Functions | 〇 | 〇 | 〇 |

### サンプルプロジェクト
[サンプルプロジェクト](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/create-sample-projects.html)

AWS Step Functions コンソールで、以下の画面にてサンプルプロジェクトのいずれかを選択すると、ステートマシンの [コード]、[ビジュアルワークフロー]、およびプロジェクトに関連するすべての AWS リソースが自動的に作成される

![004_SampleProject.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/8f554cf3-c1c7-40c7-523f-9a22e6f42845.png)

各サンプルプロジェクトは完全に機能するステートマシンが提供され、その動作に必要な関連リソースが作成される
サンプルプロジェクトを作成すると、Step FunctionsはAWS CloudFormationを使用して、ステートマシンが参照する関連リソースを作成する

### テンプレート
[Step Functions のテンプレート](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/concepts-templates.html)

Step Functions コンソールにて、以下のようにステートマシンテンプレートを選択すると、States言語の共通パターンのコードが自動的に入力される

![006_template_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/f88cb6d7-de35-752e-f045-1b0a34537df3.png)

下記の赤いボックスの部分だけ埋めれば、失敗のリトライ処理が完成される。

![006_template_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/839832c7-6499-29b9-13ae-41226a8fa746.png)


### 制限（クォータ）
[クォータ](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/limits-overview.html)
[標準ワークフロー](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/limits.html)と[Expressワークフロー](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/express-limits.html)は制限の基準が一部異なる

| クォータ | 標準ワークフロー | Expressワークフロー |
|:-:|:-:|:-:|
| 最大実行時間 | **1 年** | **5 分** |
| 実行履歴の最大サイズ | **25,000 イベント** | **無制限** |
| 最大実行アイドル時間 | 1 年 | 5 分 |
| 実行履歴の最大保持期間 | **90 日間** | [CloudWatch Logs](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/cw-logs.html)にてロギングを設定必要 |
| 最大タスク実行時間 | **1 年** | **5 分** |
| Step Functions がキューにタスクを保持する最大時間 | 1 年 | 5 分 |
| Amazon リソースネーム (ARN) あたりの最大アクティビティポーラー | ARN あたりに GetActivityTask を呼び出すポーラー数: 1,000 | 未適用 |
| タスク、状態、実行の最大の入力または結果データサイズ | 32,768 文字 | 32,768 文字 |

**※サポートセンターを使用して、リージョンごとにリソースのクォータの引き上げ申請可能**


### 料金体系
[料金表](https://aws.amazon.com/jp/step-functions/pricing/)
標準ワークフローとExpressワークフローは価格設定の基準が異なる

|  | 標準ワークフロー | Express ワークフロー |
|:-:|:-:|:-:|
| 価格設定基準 | 状態移行 | リクエスト数、実行期間 |
| 無料利用枠 | 状態移行 4,000回/月 | - |
| 料金発生**(1)** | 状態移行　1USD/40,000回 | リクエスト 1USD/100万件<br />期間　メモリ・GB-秒によって異なる |

- (1) 料金発生：標準ワークフローは無料軸の4,000回以後から料金発生

#### Express ワークフローの使用期間による料金計算
##### GB-Hour別請求表（USD, Per Hour）
※料金請求の単位は**100ms**だが、下記請求表は可読性の為１時間単位に数値変更
もっと詳しく知りたい場合は、上記リンク参照

| メモリー（MB） | 最初の1,000 GB-Hour | 次の4,000 GB-Hour | その後の追加GB-Hour |
|:-:|:-:|:-:|:-:|
| **1024** | 0.06000 | 0.03000 | 0.01642 |
| 64 | 0.00375 | 0.00187 | 0.00102 |
| 128 | 0.00750| 0.00375| 0.00205 |
| 192 | 0.01125 | 0.00562 | 0.00308 |
| 256 | 0.01500 | 0.00750 | 0.00410 |
| 追加64MBごと | 0.00375 | 0.00187 | 0.00102 |

※公式ドキュメント説明では、**GB-Hour計算のため、メモリー容量1024MBを基準**で説明している

- 測定期間
    - ワークフローの**開始から終了まで**の時間 (100 ミリ秒単位切り上げ)
- 請求されるメモリー
    - ワークフローの実行に使用されるメモリ量を基準に、**64 MB チャンク単位**で請求
    - ex) 使用されるワークフローメモリーが70MBの場合、128MBの料金を請求
- 使用されるワークフローメモリー
    - **メモリ使用量 + ステートマシン定義サイズ + (実行データサイズ x 並列実行数またはMapステップ数)**
- GB-Hour
    - **ワークフロー件数 x ワークフローの平均期間 x (請求メモリー/1024)**
    - ex) 1か月に100万件、平均期間10秒、請求メモリー64MBの場合<br />100万件 x 10秒 x (64MB / 1024MB) = 625,000 GB/S

### Step Functions のタグ付け
[Step Functions のタグ付け](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/concepts-tagging.html)
AWS Step Functions は、ステートマシン (標準と Express の両方) とアクティビティのタグ付けをサポートする

#### タグ付けの効果
- コスト割り当
    - コスト割り当てのためにはStep Functions リソースを整理して識別する必要がある<br />⇒ステートマシンやアクティビティの目的を識別するメタデータタグを追加可能（リソースが多数ある場合に特に便利）
- セキュリティ
    - [IAM のResource Tagを利用し、AWS リソースへのアクセス制御](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_tags.html)

### データサイエンス SDK
[AWS Step Functions Data Science SDK for Python](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/concepts-python-sdk.html)
データサイエンティストが Amazon SageMaker と Step Functions を使用して機械学習モデルを処理および公開するワークフローを簡単に作成できるオープンソースライブラリ、AWS Step Functions Data Science SDKを提供


## ケースによる使い方
以下の複数のケースで、Step Functionsをどう使うべきか考えてみる

### 複数のプロエスを持つサービス
10個以上のプロセスを持つサービスをAWS Lambdaで実装する場合から、
なぜこの場合Step Functionsが優秀なのかを考えてみる

#### 評価項目
| 項目 | 詳細 |
|:-:|:-:|
| **メンテ性** | メインテナンスを考慮したソースコードであること |
| **便利性** | 簡単に作成・ビルド・運用できること |
| **ステート管理** | 処理の進行状態がわかるようにしたい |
| **エラー処理** | エラー・タイムアウト・リトライ処理 |
| **監視機能** | 発生するイベントに対してログ記録できること |
| **経費** | 回避できる経費は払いたくない |
| **スケイルアウト** | サーバの横型拡張 |

#### 既存の処理
① メソッド呼び出し
一つのLambda Functionの中ですべての処理を実装
<img width="250" alt="Lambda_Only.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/f2dbeb1e-992b-31e3-b0c6-8df15379cc92.png">

| 項目 | 評価 | 詳細 |
|:-:|:-:|:-:|
| メンテ性 | × | ソースが長くなり、可読性悪い |
| 便利性 | 〇 | 一つのFunctionだけなので、簡単に運営できる |
| ステート管理 | × | 最終成功か失敗のみ |
| エラー処理 | × | リトライ処理など難しい |
| 監視機能 | 〇 | CloudWatch連携可能 |
| 経費 | 〇 | 実行時間分なので、無駄な支出なし |
| スケイルアウト | 〇 | Auto Scaling |

② 関数チェイニング
複数のLambda Functionに分け、FunctionからFunctionを呼び出す
<img width="250" alt="Lambda_Multiple.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/22319280-5a64-e0e0-1170-a4e3296b92a2.png">

| 項目 | 評価 | 詳細 |
|:-:|:-:|:-:|
| メンテ性 | △ | ソースは短くなったけど、Functionが直接繋がってる |
| 便利性 | 〇 | 複数のLambda Functionだけなので、簡単に運営できる |
| ステート管理 | × | 最終成功か失敗のみ |
| エラー処理 | × | リトライ処理など難しい |
| 監視機能 | 〇 | CloudWatch連携可能 |
| 経費 | 〇 | 実行時間分なので、無駄な支出なし |
| スケイルアウト | 〇 | Auto Scaling |

③ データベースによる作業調整
複数のLambda Function + DynamoDBで状態保存
<img width="300" alt="Lambda_with_db.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/78d8bc22-d5a7-8dfe-624a-e3a982d17353.png">

| 項目 | 評価 | 詳細 |
|:-:|:-:|:-:|
| メンテ性 | △ | ロジックとは関係ないDynamoDBへの入出力処理が増えた |
| 便利性 | △ | 運営するものが増えた |
| ステート管理 | 〇 | DBを使って管理 |
| エラー処理 | △ | 書けばできる |
| 監視機能 | 〇 | CloudWatch連携可能 |
| 経費 | △ | DynamoDBは状態管理に使うには大きい |
| スケイルアウト | 〇 | Auto Scaling |

④ Queueによる作業調整
複数のLambda Function + SQSで状態保存
<img width="300" alt="Lambda_with_queue.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/50a9d7a0-992e-834a-a2e4-4c39f738bf36.png">

| 項目 | 評価 | 詳細 |
|:-:|:-:|:-:|
| メンテ性 | △ | ロジックとは関係ないSQSへの入出力処理が増えた |
| 便利性 | △ | 運営するものが増えた |
| ステート管理 | 〇 | SQSを使って管理 |
| エラー処理 | △ | 書けばできる |
| 監視機能 | 〇 | CloudWatch連携可能 |
| 経費 | ◎ | [SQSは月100万件まで無料](https://aws.amazon.com/jp/sqs/pricing/) |
| スケイルアウト | 〇 | Auto Scaling |

#### Step Functionsの場合
複数のLambda Function + Step Function連携

<img width="300" alt="Lambda_with_step_functions.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/9ecd9641-55e1-5098-3785-b965465aea54.png">

| 項目 | 評価 | 詳細 |
|:-:|:-:|:-:|
| メンテ性 | 〇 | 各Lambda Functionでは、一つの処理に対してのロジックのみを実装<br />各Logicを繋ぐ処理はStep Functions担当 |
| 便利性 | 〇 | Step Functionsでまとめてする感じ |
| ステート管理 | ◎ | **基本機能** |
| エラー処理 | ◎ | **基本機能** |
| 監視機能 | ◎ | **ログはすべて残る**＆CloudWatch連携可能 |
| 経費 | 〇 | 1USDで状態移行40,000回 |
| スケイルアウト | 〇 | Auto Scaling |

### 標準とExpressの選択
#### Expressワークフローの特徴
Expressワークフローは、短期間（5分以内）に大量のデータを高速で処理（毎秒100,000件以上）するのに適切なワークフローである
「標準・Expressワークフロー」より一部抜粋

| 比較項目 | 標準ワークフロー | Expressワークフロー |
|:-:|:-:|:-:|
| 適切な作業 | 長時間実行され、耐久性が高く、監査可能なワークフロー | **大容量のイベント処理ワークロード** |
| 使用例 | 機械学習モデルのトレーニング、<br />レポート生成、<br />IT の自動化、<br />注文処理など | IoT データの取り込み、<br />ストリーミングデータの処理と変換、<br />大量のマイクロサービスオーケストレーションなど |
| 最大期間 | 1年 | **5分** |
| 最大実行アイドル時間（最大遊休時間）| 1年 | **5分** |
| サポートされている実行開始レート | 毎秒 2,000 以上 | **毎秒 100,000 以上** |
| サポートされている状態遷移レート | 1アカウント・1秒あたり 4,000 以上 | **無制限** |

#### Expressワークフローのサンプル
Step Functionsのサンプルプロジェクトでは、Expressワークフローのサンプルを二つ提供している

<img width="733" alt="sample_express.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/efb31478-2a45-fc2b-0a8e-806a19f60d23.png">

##### Expressワークフローのみ使用
[Amazon SQS からの大容量メッセージの処理](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/sample-project-express-high-volume-sqs.html)

Expressワークフローは、速度がすごく早いため、大容量のイベント処理やストリーミングデータワークロードに適切である
以下はAmazon SQS からの大容量メッセージを処理するサンプルプロジェクトである

<img width="160" alt="express.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/a1530dbb-32aa-8b13-c27b-f5098c9556b6.png">


##### 標準ワークフローとExpressワークフローを結合したサンプル
[選択的チェックポイントの例](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/sample-project-express-selective-checkpointing.html)

Step FunctionsからStep Functionsを呼び出すことができるのを利用し、標準ワークフローの中で一部をExpressワークフローにすることもできる
以下のサンプルプロジェクトでは、E-Commerceシステムを標準ワークフローを親ワークフローとし、高速処理が必要なバックエンドシステムの構成をアップデートする部分だけをExpressワークフローで作成して呼び出している

<img width="482" alt="standard_and_express.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114660/b25f7055-35b0-a266-5d01-a1f085064d3d.png">



### その他Step Functionsのユーズケース
[AWS Step Functions - The Ultimate Guide](https://serverless.com/aws-step-functions/#drawbacks)

- Serverless Workflow Orchestration
    - 各種Serverless Functionを繋げ、Workflowにすること
    - これはStep Functionsの存在意義でもある
- Data ETL (Extract-Transform-Load)
    - データウェアハウス-システム間のデータ移動（ETL）をStep Functionsで自走化
- AWSサービス間のデータ処理
    - LambdaとSQS、SNSなどを簡単につなげる

### Step Functionsを使ってはいけない処理
Lambdaだけで簡単に終わる機能は、Step Functionsにする必要なし
		
## まとめ
### Tip
#### AWS Step Functions Local
[Step Functions Local (ダウンロード可能バージョン) のセットアップ](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/sfn-local.html)

AWS Step Functionsは、Localで実施可能

- .jarファイルと[Docketイメージ](https://hub.docker.com/r/amazon/aws-stepfunctions-local)で提供
    - jarファイルの場合、AWS CLIの設置も必要
- 基本的に**フェイクアカウントと認証情報を使用**
    - AWS リージョンは 米国東部（バージニア北部） に設定
    - AWS Lambdaやその他のサポートされているサービスと一緒に使用するには、認証情報とリージョンなど、[オプション設定](https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/sfn-local-config-options.html)必要
- [AWS SAM (AWS サーバーレスアプリケーションモデル)](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/what-is-sam.html)のセットアップで、ローカルでLambdaが使える
    - AWSにコードデプロイせず、ステートマシンとLambdaのテストが可能

### 長所・短所
#### 長所
- 簡単に構築・実行
    - フローを視覚的に確認しながら実装
    - 実行状況を視覚的に確認できる
- リトライ・終了処理などをStep Functionsで提供
    - Lambdaでは一つの処理ロジックに集中できるので、コードがシンプルになる
    - リトライ・終了処理などの実現のため、AWSリソースを使う必要なし
- Demand-based Pricing
    - 事前コストがなく、使った分だけ払えばよいので費用がカットできる
    - 1USDで状態移行40,000回で、料金自体もそこまで高くはない

#### 短所
- 複数サービスを利用することによって
    - 各サービス別に様々な制限がある為、各種制限に引っ掛かりやすそう
    - 単一サービスに比べ、コストの予測が難しい
    - ラーニングカーブがある
        - Step Functions自体はそこまで難しくないが…
        - 様々なサービスが使えるけど、各サービスに関して分かってないと使えない

### 使ってみて分かったこと
- 前回のLambdaの延長
- JSONで簡単に作れるのに、実際のサービスにそのままつながるというのが驚き
- 今回自分で実装したのはLambdaを複数使ったくらいだっだけど、いつか他のサービスも色々含めたサービスを作成してみたい
- ドキュメントは確かに母国語で書かれてるのに、全然理解できなくて大変だった

### その他参照
[Black Belt Online Seminar:AWS Step Function](https://www.slideshare.net/AmazonWebServicesJapan/20190522-aws-black-belt-online-seminar-aws-step-functions)