はじめに
本記事はAWSで提供されているサーバレスサービスを使用し、文章の感情分析および翻訳を行うサービスを構築するハンズオンです。
全3記事の構成となっています。
- AWSサーバレスアーキテクチャで文章解析サービスを構築する その1
- AWSサーバレスアーキテクチャで文章解析サービスを構築する その2
- AWSサーバレスアーキテクチャで文章解析サービスを構築する その3
全てのハンズオンを完了すると以下のサービスについて基本的な使い方を理解できるようになります。
- AWS Step Functions
- Amazon S3
- Amazon EventBridge
- Amazon API Gateway
- Amazon DynamoDB
- Amazon Translate
- Amazon Comprehend
構築する最終的なアーキテクチャは以下の通りです。
記念すべき第1回では、本サービスの中核となるAWS Step Functions(以降、 `Step Functions`` と呼ぶ)に関する基本概念を座学と簡単なハンズオンを通して理解していただきます。
注意①
本資料内スクショのAWS管理コンソールのデザインは資料作成当時のものです。
デザインは今後変更される可能性があり、スクショと差異がある場合がありますのでご了承ください。
注意②
ハンズオンで作成したリソースについてはハンズオン終了後、各自削除をお願いします。
ゴール
- Step Functionsの特徴およびユースケースを理解していただく
- Step Functionsの基本概念を理解していただく
- Step Functionsのインプットとアプトプットを理解していただく
- Workflow Studioで簡単なステートマシンを作成し、Step Functionsに慣れる
Step Functionsとは?
Step FunctionsはAWS公式で以下のように説明されています。
AWS Step Functions は、デベロッパーが AWS のサービスを利用して分散型アプリケーションを構築し、プロセスを自動化し、マイクロサービスのオーケストレーション、データと機械学習のパイプラインを構築できるようにするビジュアルワークフローサービスです。
具体的にいうとStep Functionsは以下のようなサービスと言えます。
- アプリ、サービスの流れの制御(処理順序、並列実行、条件分岐、エラーハンドリング)を簡単に実装できるサービス
- GUIツール(Workflow Studio)でアプリ、サービスの流れを可視化、編集できる
- AWS Lambdaなどのサービスを使って分散型アプリ、マイクロサービスを構築できる
なお、本サービスは2016年12月に一般公開されました。
Step Functionsができた背景
私見ですが、Step Functionsができた背景は2つあると考えています。
- マイクロサービス的なシステム設計の台頭
- 分散アプリケーション、マイクロサービスをより簡単に構築したいというニーズの増加
マイクロサービス的なシステム設計の台頭
まず、マイクロサービスとは何なのかをみていきます。
AWSの記事によるとマイクロサービスの定義は以下です。
マイクロサービスは、小さな独立した複数のサービスでソフトウェアを構成する、ソフトウェア開発に対するアーキテクチャ的、組織的アプローチです。各サービスは、正確に定義されたAPIを通じてやり取りします。
Wikipediaではマイクロサービスは以下のように定義されています。
マイクロサービス(英語:microservices)とは、ソフトウェア開発の技法の1つであり、1つのアプリケーションを、ビジネス機能に沿った複数の小さいサービスの疎に結合された集合体として構成するサービス指向アーキテクチャ(service-oriented architecture; SOA)の1種である。
2014年、ThoughtWorks社のマーチン・ファウラーとジェームス・ルイスが提唱したソフトウェアアーキテクチャである。
まとめるとマイクロサービスの定義は以下です。
-
2014年に誕生したソフトウェアアーキテクチャないしソフトウェア開発技法 - 1つのアプリケーションを機能単位の小さなサービスとして分割し、各サービスはAPIで疎通する
日本の大手調査会社SDKI Inc.の2021年の調査によると、マイクロサービスアーキテクチャ市場は2022年から2031年の間で大幅に増加するという予想結果がでました。
このことから、アプリケーションにマイクロアーキテクチャや分散アーキテクチャを採用するケースが増えていき、その役割の一つを担うStep Functionsも重用されていくサービスになると考えられます。
分散アプリケーション、マイクロサービスをより簡潔に構築したいというニーズの増加
Step Functionsが発表される前まで、同等の機能を持つサービスとしてAmazon Simple Workflow Service(通称、SWF。2012年リリース)がありました。
このサービスは先述したような複数のAWS Lambda(2014年リリース)や他サービスを組み合わせ、一つのアプリケーションを構築するものです。
しかし、AWSは現在特殊な事情がない限りSWFではなく、Step Functionsの利用を推奨しています。理由は、SWFはJava or Rubyでの実装が必要であり、開発が複雑になる、学習コストがかかるからです。(よくある質問「Q: Amazon SWF と AWS Step Functions はどのように使い分ければよいですか?」)
分散アプリケーション、マイクロサービスの採用数が増え、より低コストで簡単に構築したいというニーズが増えたため、Step Functions(2016年にリリース)が誕生したのではないかと考えます。
Step Functionsのユースケース
Step Functionsはどのような使われ方をするのか見ていきます。
以下3ケースを例として説明します。
- マイクロサービスオーケストレーション
- AWS内の運用オペレーションの自動化
- 機械学習モデルのトレーニング、データ変換処理
マイクロサービスオーケストレーション
マイクロサービス的なシステム設計の台頭でお話ししたように、マイクロサービスを実現する際にStep Functionsを使用することがあります。
AWS内の運用オペレーションの自動化
AWS内部でのセキュリティ対応などの運用オペレーションでStep Functionsが使用されることがあります。
リンク記事では、AWSのセキュリティサービスで不正な動きをしたEC2の通信を遮断する設定を自動追加するフローをStep Functionsで実現しています。
機械学習モデルのトレーニング、データ変換処理
ワークフローが明確になっている場合、フローを可視化をすると開発効率化につながります。
機械学習はデータの加工、学習、推論など作業の流れが明確であるため、Step Functionsが採用される場合があります。
Step Functionsの基本概念
Step Functionsを使う上で事前に知っておくべき用語、機能、構成要素について説明します。
- Workflow Studio
- ワークフロー
- ステートマシン
- ステート
- ASL(Amazon States Language)
Workflow Studio
下記はWorkflow Studioのスクショです。赤枠部分がWorkflow Studioに当たります。
- ドラッグ&ドロップで
ステートマシン(後述)(つまり、ASL(後述))を作成することができるGUIツール
ワークフロー
- 業務処理の流れ(ビジネスプロセス)
-
ステートマシン(後述)で表現される
ステートマシン
下記スクショの赤枠部分がステートマシンに当たります。
-
ワークフローをStep Functionsの機能を利用して表現したもの - 複数の
ステート(後述)を束ねた単位 -
ASL(後述)を使用して定義される
ステート
下記スクショの赤枠部分がステートに当たります。
- AWSサービスの実行、条件分岐、並列処理などの1処理を実行する単位
-
ステートマシンは複数のステートから構成される
ASL(Amazon States Language)
下記スクショの赤枠部分がASLに当たります。
-
ステートマシン内のステートの状態遷移を表現するために使用されるJSON形式の独自言語 - Step Functionsの実体と言える
ASLについて
先述したように、ステートマシンはJson形式の独自言語であるASL(Amazon States Language)で定義されます。
ASLの記載項目について以下2つの定義を説明します。
- ステートマシンの定義
- ステートの定義
ステートマシンの定義
| フィールド名 | 必須/非必須 | 説明 |
|---|---|---|
| Comment | オプション | ステートマシンの説明 |
| StartAt | 必須 | どのステートから実行するか。ステート名を指定 |
| TimeoutSeconds | オプション | ステートマシンのタイムアウト時間を秒数で指定 |
| Version | オプション | ASLのバージョン。デフォルトは1.0 |
| States | 必須 | 実行するステート。詳細はステートの定義参照 |
ステートの定義
| フィールド名 | 必須/非必須 | 説明 |
|---|---|---|
| Type | 必須 | ステートの種類。詳細はType参照 |
| Next | オプション | 現在のステートが終了した後に実行するステート名 |
| End | オプション | この値がtrueの場合、このステートが終了したらステートマシンの終了を表す |
| Comment | オプション | ステートの説明 |
| InputPath | オプション | ステートの入力の一部をフィルタリングして新しい入力とするパス |
| Parameters | オプション | ステート内のLambda関数などの入力とするJsonを指定する |
| OutputPath | オプション | ステートの出力の一部をフィルタリングして新しい出力とするパス |
| ResultPath | オプション | ステート内のLambda関数などの出力をステートの入力に何という名前で埋め込むか指定する |
Type
ステートは8種類あり、フィールドTypeの値によって、必要なフィールド、構造が異なる。
| Type | 説明 |
|---|---|
| Task | ステートマシンで実行する作業(AWSサービスなど)を定義する |
| Choice | ステートマシンに条件分岐を設定する |
| Fail | ステートマシンの実行を失敗で停止させる |
| Succeed | ステートマシンの実行を成功で停止させる |
| Pass | 何の処理もせず、入力を出力に渡す |
| Wait | 指定された時間待機し、指定されたステートに遷移する |
| Parallel | このステート内で定義したステートを並列実行する |
| Map | 入力配列の要素毎にステートを順次実行または並列実行する |
ハンズオン
では、実際に手を動かし、Step Functionsがどのようなものなのか体験してみましょう。
最終的に作成するサービスのアーキテクチャ図を再掲します。
最初は小さな動くシステムを作り、そこから徐々に機能を追加して、下のシステムを実際に構築していきます。
このシステムは簡単にいうと文章解析サービスであり、内容を箇条書きすると以下です。
- 日本語が記載されたテキストファイルを入力するとその文章を英語翻訳する
- 日本語が記載されたテキストファイルを入力するとその文章を感情分析する
- 上記分析結果をデータベースに保管する
- REST APIで入力となるテキストファイルをアップロードする
Step Functionsが中核となるサービスであることから、上記サービスの構築に取り掛かる前にStep Functionsの基礎的な部分、重要な部分をハンズオンを通して体験します。
前準備
ハンズオンを実施するための準備します。
S3バケットの作成
画面上部にある検索窓にs3と入力し、検索結果にS3が表示されるので、クリックしてください。
オレンジ色のバケットを作成ボタンを押下してください。
S3バケットに関する設定入力画面に遷移します。
バケット名に{ユーザ名}-{実施年月日}を入力してください。
なお、バケット名は全世界で一意にする必要があります。もし、作成時にバケット名はすでに存在しますなどのエラーが発生した場合はバケット名の末尾に乱数など付与し、再実施してください。
その他設定はデフォルト値で構いません。
最後に画面最下部にあるバケットを作成ボタンを押下してください。
画面上部に成功メッセージが表示されればバケットの作成完了です。
ステートマシンの作成
続いてステートマシンを作成しましょう。
画面上部にある検索窓にstepと入力し、検索結果にStep Functionsが表示されるので、クリックしてください。
オレンジ色のステートマシンの作成ボタンをクリックしてください。
そのまま次へボタンをクリックしてください。
Workflow Studioが表示されます。
左メニューでフロータブを選択し、Passを中央画面のStartとEndの間にドラッグ&ドロップしてください。
続いて、右上の次へボタンをクリックしてください。
確認画面が表示されます。
Workflow Studioで生成したASLとステートマシンが表示されます。
確認したら右下の次へボタンをクリックしてください。
ステートマシンに関する設定を入力します。
ステートマシン名は適当な名前を入力し、それ以外はデフォルト値にしてください。
最後にステートマシンの作成ボタンを押下してください。
画面上部に成功メッセージが表示されればステートマシンの作成完了です。
ステートマシンの実行
作成したステートマシンを実行してみます。
上記画面右上にある実行を開始ボタンを押下するとダイアログが表示されます。
ダイアログではステートマシンのインプットとなるJson文字列を入力に指定します。
今回は下記Jsonを入力します。
実行を開始ボタンをクリックし、ステートマシンを実行します。
{
"first": 1,
"second": 2
}
実行結果画面が表示されます。
画面上部の実行ステータスでステートマシンが最終的に成功か失敗したか表示されます。
また、画面中央のグラフビューでステート毎の処理の成否を視覚的に確認することができます。
ステートの詳細情報を確認することもできます。
画面中央のグラフビューのPassステートをクリックし、ステップの詳細の入力タブを選択すると、当該ステートのインプットとなったJson文字列が表示されます。
今回はステートマシン実行時に指定したJson文字列が入力となっています。
続いて出力タブを選択してみます。
出力タブには当該ステートがアウトプットしたJson文字列が出力されます。
Passステートは何の処理もせず、入力を出力に渡す機能です。また、今回OutputPathなど指定していないため、入力のJson文字列がそのまま出力されます。
ステート間の入出力制御(InputPath/Parameters/OutputPath/ResultPath)を体験する
続いて、ステート間のパラメータ、つまりJson文字列の受け渡しについて確認します。
ここは仕組みが多少理解しづらく、重点的に説明すべきと感じたため、章を設けました。
ステートの定義でInputPath、Parameters、OutputPath、ResultPathについて説明しました。
これら設定はWorkflow Studioでステートを選択し、入力、出力タブなど選択すると指定することができます。
これら設定は例えば以下の場合に使用します。
- 当該ステート内では、入力されたJsonの一部を使用したい
- 当該ステートの出力は、入力Jsonそのものではなく、独自の形式で返したい
つまり、これら設定はステートの入出力の加工、フィルタリングを指定するものです。
データフローシミュレーターを使用すると手軽にInputPath、Parameters、OutputPath、ResultPathなどの設定を試すことができます。
左メニューのデータフローシミュレーターをクリックしてください。
次にステート入力にステートの入力となるテスト用のJsonを入力します。
今回は以下のJsonを入力します。
入力したら次へをクリックしてください。
{
"first": "1",
"second": "2",
"third": {
"first": "3-1",
"second": "3-2"
}
}
InputPath
まずはInputPathの設定です。
フィルタ条件を指定することで入力Jsonの一部のみフィルタリングしてステートに渡すことができます。
今回は以下を入力します。
$はJson全体を表しており、.の後にフィルタリングする各要素のJsonキー名を指定します。
下記の場合、入力JsonのJsonキーthirdに定義したオブジェクトを取得するよう指定しています。
$.third
フィルタリング後の結果は以下になります。
{
"first": "3-1",
"second": "3-2"
}
データフローシミュレーターを使用すると加工、フィルタリング前のJsonとその後のJsonが一目で確認できるため、とても便利です。
Parameters
続いて、Parametersです。
こちらはステートの入力をInputPathの結果と異なる形式で渡したい場合に指定します。
InputPathの結果がこの設定で上書きされるイメージです。
.$や$.は元となるJson(InputPathの結果)の値を参照したい場合、キーと値に指定する必要があります。
以下だと$.first、$.secondが指定されています。
InputPathのフィルタリング後のJsonの値、つまり、"3-1"、"3-2"がそれぞれ埋め込まれます。
{
"staticValue": "Just a string",
"third": {
"first.$": "$.first",
"second.$": "$.second"
}
}
結果は以下になります。Parametersに設定したJsonにInputPathの結果が埋め込まれ出力されていることがわかるかと思います。
{
"staticValue": "Just a string",
"third": {
"first": "3-1",
"second": "3-2"
}
}
Task ResultとResultSelector
続いて、Task Result、ResultSelectorですが、こちらはLambda等の結果とそのフィルタリング設定です。
今回は触らないので説明は割愛させていただきます。
値は両方とも空にしてください。その場合、Parametersの結果がそのまま出力されます。
ResultPath
次にResultPathです。
ResultSelectorのフィルタリング後の結果を、最初の入力Jsonのどこに挿入するか指定できます。
下記は入力Json($)直下にresultというキーを追加するよう指定しています。
そして、result配下にResultSelectorのフィルタリング後のオブジェクトを追加するよう指定しています。
$.result
結果は以下になります。
{
"first": "1",
"second": "2",
"third": {
"first": "3-1",
"second": "3-2"
},
"result": {
"staticValue": "Just a string",
"third": {
"first": "3-1",
"second": "3-2"
}
}
}
OutputPath
最後はOutputPathです。
ResultPathの結果のフィルタリングを設定します。
下記の場合、Jsonキーresultに定義したオブジェクトを取得するよう指定しています。
$.result
フィルタリング後の結果は以下になります。
{
"staticValue": "Just a string",
"third": {
"first": "3-1",
"second": "3-2"
}
}
ステート間の入出力制御についてデータフローシミュレーターを使用し、体験してみました。
実際にステートの設定を変更することで入出力制御の確認もできますが、フィルタリングの途中経過がわからないのでデータフローシミュレーターはとても便利だと感じます。
是非活用してみてください。
なお、入出力制御のより詳しい説明は以下の記事をわかりやすいので参考にしてください。
様々なステートタイプを試してみる
注意
本章で作成するステートマシンは冗長な部分があります。
例えば、GetObjectステートでエラーが発生した際、Passステート、Choiceステート経て、Failステートに遷移しますが、本来はそのような実装は不要であり、直接Failステートに遷移させれば良いです。
あくまでハンズオン用としてご了承ください。
Typeでステートが8種類あると紹介しました。
今回はTask、Pass、Choice、Fail、Successについてハンズオンを通して体験してみます。
まず、ステートマシンの作成で自分が作成したステートマシンのリンクをクリックしてください。
次に編集ボタンをクリックしてください。
右側にあるWorkflow Studioボタンをクリックしてください。
Task、Passタイプのステートの追加と遷移先指定
Passがあった部分を選択し、削除ボタンで削除してください。
次に左上の検索窓にs3 getobjectと入力し、一番上にあるGetObjectステートをPassステートがあった場所にドラッグ&ドロップしてください。
ステートマシンが以下のようになっていることを確認してください。
GetObjectステートは指定したS3バケットから指定したファイルを取得するTaskタイプのステートです。
今回はファイルの存在確認という目的で使用します。
右側のメニューにAPIパラメータがあります。
BucketにはS3バケットの作成で作成したS3バケットの名前、Keyにはfinish.txtと入力してください。
次に、PassステートをGetObjectステートの後に追加します。
このステートはGetObjectステートでエラーが発生した際の遷移先として設定します。
右側の状態名はPass-Failにしてください。
ステートマシンが以下のようになっていることを確認してください。
続いて、Pass-Failを選択し、左メニューの出力タブを選択します。
結果に以下のJsonを入力してください。
これにより、Pass-Failステートが最終的に出力するJsonを指定できます。
Pass-Failステートの後に実行されるステートの入力はここで指定したJsonになります。
{
"error": "hoge"
}
次に、PassステートをGetObjectステートとPass-Failステートの間に追加します。
このステートはGetObjectステートが成功した際の遷移先として設定します。
状態名はPass-Successとしてください。
また、次の状態を最後に移動に変更してください。
ステートマシンが以下のようになっていることを確認してください。
続いて、Pass-Successステートを選択し、左メニューの出力タブを選択します。
結果に以下のJsonを入力してください。
これにより、Pass-Successステートが最終的に出力するJsonを指定できます。
Pass-Successステートの後に実行されるステートの入力はここで指定したJsonになります。
{
"error": ""
}
エラーハンドリング(キャッチャー)の追加
GetObjectステートでエラーが発生したらPass-Failステートに遷移させるようにします。
GetObjectステートを選択し、左メニューエラー処理タブを選択し、新しいキャッチャーの追加をクリックしてください。
Errorsはキャッチするエラーの種類を定義します。States.ALLを入力してください。
この設定はステート内の全てのエラーをキャッチする設定です。
Javaで言うtry-catch構文でExceptionをキャッチしているイメージになります。
Fallback stateはErrorsで指定したエラーが発生した場合の遷移先を指定します。Pass-Failを選択してください。
Choice、Success、Failタイプのステートの追加と条件分岐による遷移
続いて、Choiceステートを追加します。
左メニューからChoiceを選択し、Pass-Successの後に追加してください。
Pass-Failステートを選択し、設定タブで次の状態をChoiceに変更してください。
Choiceステートはif文のようなもので指定した条件に一致したら指定したステートに遷移させることができます。
今回はPass-Success、Pass-Failが出力したJsonの内容を見て、SuccessステートかFailステートに遷移させます。
Choiceステートに伸びている矢印でDefaultが付いている方にSuccessステートを追加してください。
Rule #1が付いている方にFailステートを追加してください。
Choiceステートの条件を指定します。
Choiceステートを選択し、右メニューにRule #1があるのでクリックしてください。
次にThen next state isでFailを選択してください。
続いてAdd conditionsボタンを押下してください。
条件入力ダイアログが表示されます。
Variableは$.error、Operatorはmatches string、Valueは*hoge*を入力してください。
Variableの設定はInputPathなどの書き方と同様です。
これはPass-Success、Pass-Failの出力Jsonのキーerrorの値にhogeという文字列が含まれていたら、条件に一致すると判定するRuleです。
{
"error": "hoge"
}
最後に条件を保存するボタンをクリックしてください。
以上でステートマシンが一通り完成しました。
右上の適用して終了ボタンをクリックしてください。
IAMロールに権限(IAMポリシー)を追加
作成したステートマシンを実行してみます。
結果は失敗になります。GetObjectステートをクリックし、出力タブでエラー内容を確認してみましょう。
Causeに出力されるメッセージにStatus Code: 403とあります。これは権限が不足していることに起因するエラーです。
作成したステートマシンにS3バケットにアクセスする権限がないためエラーになっています。ステートマシンにS3バケットを操作する権限を与える必要があります。
ステートマシンにはIAMロールというアイデンティティが付与されています。
IAMロールはIAMポリシーという実際の操作権限の集まりであり、IAMロールをステートマシンなどのAWSリソースに与えることでリソースはIAMポリシーに定義された操作権限を得ることができます。
今回ステートマシン作成時にIAMロールが自動生成されています。
そのIAMロールにS3バケットを操作するIAMポリシーを付与することで今回のエラーは解決することができます。
では、当該IAMロールにIAMポリシーを与えてみましょう。
ステートマシンの詳細画面に遷移し、編集ボタンを押下してください。
画面中央にアクセス許可があります。既存のロールを表示されているIAMロールの名前をメモしてください。
次にIAM画面に遷移します。
画面上部にある検索窓にiamと入力し、検索結果にIAMが表示されるので、クリックしてください。
左メニューロールをクリックしてください。
検索窓に先ほどメモしたIAMロールの名前を入力し、表示されたロールのリンクをクリックしてください。
許可タブを選択すると許可ポリシーが表示されます。
その右上の許可を追加プルダウンを選択し、ポリシーのアタッチをクリックしてください。
検索窓にS3Fullと入力し、Enterしてください。
ポリシーAmazonS3FullAccessが表示されるのでチェックし、右下の許可を追加をクリックしてください。
許可ポリシーの一覧にAmazonS3FullAccessが表示されたら追加完了です。
以上の手順を完了すると先ほどのエラーは発生しなくなります。
以降はS3バケットにファイルがない場合とある場合でステートマシンを試してみます。
実行!(ファイルがない場合)
再度ステートマシンを実行してください。
ステートマシンの実行に失敗したと思います。
GetObjectステートを選択し、出力タブでエラーを確認します。
Causeに出力されるメッセージにThe specifed key does not exist.とあります。
これはTask、Passタイプのステートの追加と遷移先指定のGetObjectステート追加時に指定したオブジェクト(finish.txt)がS3バケットに存在しないことが原因です。
処理の流れを箇条書きしてみます。
-
GetObjectステートが実行され、指定されたファイルを取得しようと試みる -
GetObjectステートでファイルが取得できないため、エラーが発生する -
GetObjectステートで指定したキャッチャーにより、Pass-Failステートに遷移する -
Pass-Failステートの出力がChoiceステートに渡される -
Choiceステートの条件分岐で入力Jsonのerrorキーの値にhogeが含まれているため、Failステートに遷移する
実行!(ファイルがある場合)
S3バケットにfinish.txtを作成後、ステートマシンを実行します。
S3バケット一覧画面に遷移し、作成したS3バケット名をクリックしてください。
アップロードボタンを押下してください。
finish.txtファイルをドラッグ&ドロップし、右下のアップロードボタンをクリックしてください。
成功メッセージが上部に表示されればアップロード完了です。
再度ステートマシンを実行してください。
ファイルが存在するのでGetObjectステートはエラーにならず、Successステートを追加し、ステートマシンの実行に成功しました。
処理の流れを箇条書きしてみます。
-
GetObjectステートが実行され、指定されたファイルを取得しようと試みる -
GetObjectステートでファイルが取得できたため、Pass-Successステートに遷移する -
Pass-Successステートの出力がChoiceステートに渡される -
Choiceステートの条件分岐で入力Jsonのerrorキーの値にhogeが含まれないため、Successステートに遷移する
参考
- https://www.youtube.com/watch?v=PGyasNJ1QTQ&t=140s
- https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/welcome.html
- https://www.slideshare.net/AmazonWebServicesJapan/20190522-aws-black-belt-online-seminar-aws-step-functions
- https://aws.amazon.com/jp/step-functions/use-cases/
- https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/amazon-states-language-common-fields.html
- https://dev.classmethod.jp/articles/stepfunctions-parameters-inter-states/
- https://tech.nri-net.com/entry/aws_history_and_chronology_all


























































