AWS Step Functionsだけでカウントアップをする
Step Functionsで処理フローを作成している場合に、リトライ処理などで、ループ処理をしたい場合がありますが、無限には実行したくないため、リトライの回数で制御したいケースがあります。
以前はLambdaなどで実装する必要があったようですが、関数が使えるようになっていて、それを利用して簡単な計算処理ができるため、こちらの機能を使って実現してみます。
処理の流れ
カウンターを初期化
カウントアップ
続行するか判定
続行する場合
数秒待機する
No.2に戻る
続行しない場合
成功
※実際のリトライ処理などでは、失敗なども考慮する必要があります
Step Functionsのステートマシンの作成
Step Functionsのコンソールに移動して、ステートマシンの作成ボタンをクリックします。
テンプレートはBlankを選びます。
ステートマシンの作成画面が表示されたら設定タブをクリックして設定の画面を表示します。
今回は、ステートマシン名を入力して、他はすべてデフォルトのままとします。
デザインタブをクリックして、右側のステートマシンクエリ言語にはJSONPathを選択します。
JSONataは新しい方法のようで、今回は単純にどうやって使うのか分からないので、JSONPathを選択しています。今度試してみます。
次に実際に各ステップのステートを作っていきます。
初期化ステートの作成
まずは、カウントアップ用の変数を用意する最初のステートを作ります。
フローを選択して、Passステートをエリア中央の部分にドラッグ&ドロップして配置します。
Passステートの状態名を入力します。
入力/出力タブをクリックして「Parameters を使用して入力を変換」にチェックをして、表示されたテキストエリアに以下を入力します。
{
"count": 0
}
カウントアップステートの作成
次に、カウントアップ用の変数をインクリメントするステートを作ります。
Passステートを初期化ステートの下にドラッグ&ドロップして配置します。
Passステートの状態名を入力します。
入力/出力タブをクリックして「Parameters を使用して入力を変換」にチェックをして、表示されたテキストエリアに以下を入力します。
{
"count.$": "States.MathAdd($.count, 1)"
}
今回はStates.MathAddという関数を利用します。また、キー名の末尾や、受け取ったパラメータにアクセスするために$.という構文を使っていますが、この書き方をしないとJSONPathとして解釈されずに文字列として解釈されてしまいますので、Step Functionsを利用する場合は、重要なポイントです。
また、使用できる場所と使用できない場所があるため、そちらもつまずきポイントかなと思います。
リトライ判定ステートの作成
次に、現在のカウント数を見て、再度カウントアップをするのか、終了させるのかを判定させるための分岐のステートを作ります。Choiceステートをカウントアップステートの下にドラッグ&ドロップして配置します。
Choiceステートの状態名を入力します。次にChoice RulesのRule #1のエリアの鉛筆マークをクリックして、ルールの編集をしていきます。
Add conditionsボタンをクリックします。
Variableに`$.count`、Operatorに`is less than or equal to」`、Valueに`Number constant`で`3`を入力します。
これは、`$.count <= 3`という設定になり、カウントが3以下ならRule1を適用するという意味になります。
条件を保存するボタンでクリックします。
画面の方に想定通りに`$.count <= 3`と設定されたことが確認できます。
再カウントアップ前の待機ステートの作成
次に、再カウントアップ前のWaitステートを作ります。
実際のシステムにおいてリトライをしたいケースとして、他のサービスに一時的に接続できなかった、サービスのスロットリングで失敗してしまったなど、一定時間をおけば自動で復旧されるケースの場合が想定されます。そのためのWaitになります。
Waitステートをリトライ判定ステートの左側(Rule#1の方)のエリアにドラッグ&ドロップして配置します。
待機時間は今回はデフォルトの5秒として、次の状態としてカウントアップ用のステートを選択します。
成功ステートの作成
最後に、終了用の成功ステートを作ります。
実際のシステムにおいては、失敗ステートも作って、リトライしたけどだめだった、またはそもそもリトライ出来ないエラーが発生したので失敗させたいなどあるため、その考慮も必要です。今回は簡単にするために用意していません。
成功ステートをリトライ判定ステートの右側(Defaultの方)のエリアにドラッグ&ドロップして配置します。
最後に作成ボタンをクリックしてステートマシンを作成します。
ロールの作成の確認モーダルが表示されるので、確認ボタンをクリックして作成します。
動作確認
作成がされたら、実行ボタンをクリックして実行してみましょう。
実行の開始のモーダルが表示されたら、開始ボタンをクリックします。
今回は入力パラメータは必要ないので、何も入力せずに実行します。
実行が開始され、まずはWaitのステートに移動したことがグラフビューで確認することが出来ます。
しばらく待つと成功のステートも緑色になり正常に終了した状態になります。
テーブルビューのタブをクリックして、カウントアップ出来ているか確認してみると、入力ではcount: 1だったのが、出力ではcount: 2になり、カウントアップできていることがわかります。
まとめ
リトライのためのカウントアップの実現方法としてはいくつかありますが、個人的にはStepFunctionsで完結する今回の方法は良いなと感じています。
例えば、StepFunctionsが呼び出すメインとなるプログラム側にカウントアップ値を渡して、カウントアップさせて返却するということも出来ますが、StepFunctionsでのリトライは、プログラムの外側の話なのに、プログラム側がStepFunctionsの制御を持ってしまっている状態になり、StepFunctionsとプログラムの結合度が強くなってしまっています。
また、Lambdaなどの追加の実行環境を用意するのは、構成としてイマイチだなと感じていたので、StepFunctionsのみで実現できるのは嬉しいなと感じました。
その他の関数もあるため、色々とできそうですね。ただし、やりすぎるとベンダー依存度、サービス依存度が高まるので、使い所を見極めて使っていきたいですね。
IaCも作成したので興味ある方は見てください。