🐋
Step FunctionsのParameterを使って上限ありのループを作る
概要
Result Path
とParameter
を利用してループのロジックを作成しました。Lambdaで回数を制御するよりも簡易な方法です。
ステートマシン
グラフ
JSON
{
"Comment": "",
"StartAt": "Init",
"States": {
"Init": {
"Type": "Pass",
"Result": [
true,
true,
true,
false
],
"Next": "Can Execute",
"ResultPath": "$.canExecute"
},
"Can Execute": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.canExecute[0]",
"BooleanEquals": true,
"Comment": "true",
"Next": "Lambda Invoke"
}
],
"Default": "Fail"
},
"Lambda Invoke": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"Payload.$": "$",
"FunctionName": "arn:aws:lambda:ap-northeast-1:876462513854:function:sampleFunc:$LATEST"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 1,
"MaxAttempts": 3,
"BackoffRate": 2
}
],
"Next": "Is Success",
"ResultPath": "$.output"
},
"Is Success": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.output.Payload.result",
"BooleanEquals": true,
"Comment": "true",
"Next": "Success"
}
],
"Default": "Pop Element from List"
},
"Success": {
"Type": "Succeed"
},
"Pop Element from List": {
"Type": "Pass",
"Next": "Wait",
"Parameters": {
"canExecute.$": "$.canExecute[1:]"
}
},
"Fail": {
"Type": "Fail"
},
"Wait": {
"Type": "Wait",
"Seconds": 5,
"Next": "Can Execute"
}
}
}
やっていること
Init
ループの上限回数を制御するための変数を定義しています。先頭から上限回数分だけtrue
を並べた配列を定義します。
後続の処理でもこの変数が使えるように、ResultPathを設定します。
ステートマシン定義(Init部分)
"Init": {
"Type": "Pass",
"Result": [
true,
true,
true,
false
],
"Next": "Can Execute",
"ResultPath": "$.canExecute"
},
Can Execute
canExecute
の先頭の要素がtrue
の場合に後続のLambdaを実行するようにします。
ステートマシン定義(Can Execute部分)
"Can Execute": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.canExecute[0]",
"BooleanEquals": true,
"Comment": "true",
"Next": "Lambda Invoke"
}
],
"Default": "Fail"
},
Invoke Lambda
メイン処理となるLambdaを実行しています。
この例ではサンプルとしてtrue
かfalse
を返すだけの関数を実行しています。
Lambda関数
import random
def lambda_handler(event, context):
return {'result': bool(random.randint(0,1))}
ステートマシン定義(Lambda Invoke部分)
"Lambda Invoke": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"Payload.$": "$",
"FunctionName": "arn:aws:lambda:ap-northeast-1:876462513854:function:sampleFunc:$LATEST"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 1,
"MaxAttempts": 3,
"BackoffRate": 2
}
],
"Next": "Is Success",
"ResultPath": "$.output"
},
Is Success
Lambda実行結果を判定しています。true
の場合は処理終了、それ以外の場合はループ(リトライ)処理へ流します。
ステートマシン定義(is Success部分)
"Is Success": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.output.Payload.result",
"BooleanEquals": true,
"Comment": "true",
"Next": "Success"
}
],
"Default": "Pop Element from List"
},
Pop Element from List
inputとなるcanExecute
の先頭の要素をpopして、新しくoutputとすることでループの回数を制御しています。
下記のようにループが回るごとに先頭から要素がpopされていき、上限回数まで達するとCan Executeステートで実行不可と判定される仕組みです。
- 1回目:
[true, true, true, false]
→[true, true, false]
- 2回目:
[true, true, false]
→[true, false]
- 3回目:
[true, false]
→[false]
これを実現するためにParametersを使用しているのですが、Parametersについては下記を参考にさせていただきました。
また、配列の要素をpopする処理は下記を参考にさせていただきました。
Discussion