こんにちは。テクニカルディレクターのSarahです。
AWS Step Functionsで分岐処理を行うフローを作ってみたかったので、今回の記事では起動時の入力値とLambdaの関数内で生成した乱数でじゃんけんをさせ、受け取った結果で分岐するワークフローを作成してみました。
事前準備
今回は下記のような流れで行う想定です。
- Step Functions起動時に出す手を下記の対応で入力する
(文字列にしてもよかったですが、直感的にわかりやすいように今回は数字に置き換えています)グー 1 チョキ 2 パー 3 - その値をStep FunctionsからLambdaに渡して、Lambdaで生成した乱数とじゃんけんを行う
- Lambdaの結果から勝敗に応じて分岐したタスクに進み、終了
IAMロールの作成
はじめにLambda用のIAMロールを作成します。
- IAMとは
- 認証と許可の仕組み。AWSはセキュリティのベストプラクティスとして最小権限でのアクセス許可を推奨していますが、IAMを使うことでユーザー・グループ・アプリケーションなど用途や実行内容に応じて認証を行うことができます。
ロールを新規作成し、AWSのサービス > Lambdaを選択し、次のステップへ進みます。
ポリシーは特に選択せず、ロール名を付けて完了です。
Lambda関数を作成
「一から作成」を選択、関数名と使用言語を決めて関数を作成します。今回はPythonの3.9にしました。ロールはデフォルトのまま、既存のロールで先ほど作成したロールを指定します。
ソースを書いてデプロイします。
ソースコード
import random
def lambda_handler(event, context):
rand = random.randint(1, 3) #1から3までの乱数を生成
if event['InputPath'] == rand:
result = 'Tied' #入力値とrandが同じならあいこ
elif event['InputPath'] == 3 and rand == 1:
result = 'You win' #入力値が3のとき、randが1なら勝ち
elif event['InputPath'] == 1 and rand == 3:
result = 'You lose' #入力値が1のとき、randが3なら負け
elif event['InputPath'] < rand:
result = 'You win' #入力値よりもrandが大きければ勝ち
elif event['InputPath'] > rand:
result = 'You lose'#入力値よりもrandが小さければ負け
return {
"bar":result
}
(今回初めてPythonを使ったのですが、Pythonのコメントアウトの記号を知らずスラッシュでコメント書こうとしてました。あぶない👦🏻)
ステートマシンの作成
入力値をLambdaに渡し、結果に応じて分岐するフローを作成していきます。
今回は「コードでワークフローを記述」を選択しました。タイプの種類や引数の書き方など独特なので慣れるまで複雑に感じましたが、JSON形式なのでフォーマット自体はシンプルです。
コードで記述する以外にも、「ワークフローを視覚的に設計」からぽちぽち組み合わせるだけでフローを作成できます。
ソースコード
{
"Comment": "Tomato",
"StartAt": "FirstState",
"States": {
"FirstState": {
"Type": "Task",
"Resource":"作成したLamdaの実行を指定",
"Parameters":{
"InputPath.$":"$.throw"
},
"Next": "ChoiceState"
},
"ChoiceState": {
"Type":"Choice",
"Choices": [
{"Variable":"$.bar",
"StringEquals":"Tied",
"Next":"Tied"
},
{
"Variable":"$.bar",
"StringEquals":"You win",
"Next":"Won"
},
{
"Variable":"$.bar",
"StringEquals":"You lose",
"Next":"Lost"
}
],
"Default":"DefaultState"
},
"Tied":{
"Type":"Pass",
"Result":"Tied",
"Next":"LastState"
},
"Won":{
"Type":"Pass",
"Result":"Won",
"Next":"LastState"
},
"Lost":{
"Type":"Pass",
"Result":"Lost",
"Next":"LastState"
},
"DefaultState":{
"Type":"Fail",
"Cause":"Not match"
},
"LastState":{
"Type":"Pass",
"End":true
}
}
}
ステートマシン起動時に入力された値はInputPathで使用することができ、引数+キーで指定できます。
Lambdaの呼び出し方は、呼び出す関数のARNを直接指定する方法と、Lambda:invokeで呼び出す方法の2種類があります。この2つではパラメータの指定の仕方が異なり、後者の場合はParametersの中でARNを指定し、実際の引数はParametersの中のPayloadに指定する形になります。
こちらの記事でこの2つの違いが詳しく解説されていたので、参考にしてみてください。
こんな感じのフローになりました。
実行
早速実行してみます。throwというキーで出す手を指定して、ステートマシンを実行します。
無事実行されました。
Lambdaからあいこが出力され、そのままあいこのステートに進んでいるのがわかります。
おわりに
今回はStep Functionsで分岐処理があるフローを作成してみました。
LambdaやAPIゲートウェイと組み合わせたり、コールバック関数を使用して非同期処理にしたりすることで比較的複雑な処理も実現できそうなので、今後も色々試してみたいと思います。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。