初めに
Step Functions に入門してみました。操作方法などを簡単に書いておきます。
ステートマシンの作成・実行
ステートマシンのコードには ASL(Amazon States Laguage)という独自の言語が使われます。
簡単に作成してみます。以下のステートマシンは、一つのステートを実行するステートマシンです。
{
"StartAt": "State",
"States": {
"State": {
"Type": "Pass",
"Result": "State Result",
"End": true
}
}
}
これを実行してみます。実行前に以下の画面が表示されます。
「実行の開始」を押すと以下の画面が表示されます。
これでこのステートマシンの実行が完了しました。上図の左側の「State」をクリックした後、右側の「ステップ入力」をクリックすると、この「State」が入力に何を受け取ったかが表示されます。
続けて出力も見てみます。
このステートマシンは、実行が開始されると、
{
"Comment": "Insert your JSON here"
}
を受け取り、
"State Result"
を返すことがわかりました。
入力・出力の変更
入力の値を変更するには、ステートマシンを実行する前の画面において編集します。
こちらを以下のように編集します。
次に出力の値を変更します。出力の値を変更するには、以下のようにステートマシンの Result
フィールドを変更します。
{
"StartAt": "State",
"States": {
"State": {
"Type": "Pass",
"Result": "Blue",
"End": true
}
}
}
これでこのステートマシンは、
{
"Color": "Red"
}
を受け取り、
"Blue"
を返すステートマシンになりました。
入力に受け取った値を出力する
受け取った値を出力に反映させるには、InputPath
フィールドを追加し、そこに入力のキーを指定します。
{
"StartAt": "State",
"States": {
"State": {
"Type": "Pass",
"InputPath": "$.Color",
"End": true
}
}
}
入力は前回と同じですが、出力が入力の値を反映したものになりました。
次に JSON 形式で受け取った値を返す方法ですが、これには ResultPath
フィールドを追加します。
{
"StartAt": "State",
"States": {
"State": {
"Type": "Pass",
"InputPath": "$.Color",
"ResultPath": "$.Color",
"End": true
}
}
}
この出力結果は以下のようになります。
入力と出力が一致しています。実はこのように入力をそのまま出力に渡すようにするには、InputPath
と ResultPath
は必要ありません。つまり以下のコードで十分です。
{
"StartAt": "State",
"States": {
"State": {
"Type": "Pass",
"End": true
}
}
}
出力を制限する
以下のような入力を考えます。
{
"ID": "A10",
"ProductName": "Jacket",
"Color": "Red"
}
これを受けて、ID と赤色のジャケットの在庫の個数を返すステートを作成します。そのためには以下のように、OutputPath
で出力するキーを指定します。
{
"StartAt": "State",
"States": {
"State": {
"Type": "Pass",
"Result": 3,
"ResultPath": "$.Stock",
"OutputPath": "$['ID', 'Stock']",
"End": true
}
}
}
実行結果は以下のようになります。
"ResultPath": "$.Stock"
により、出力に Stock
というキーを追加しています。OutputPath
フィールドで、出力するキーを制御できます。ここでは、入力の ID
キー と、追加した Stock
キーを出力し、それ以外のキーは出力しないように制御しています。
Task ステート
ステートマシンから他の AWS リソースを実行するには、タスクステートを使用します。ステートにはいくつか種類があり、ステートの Type
フィールドで指定します。例えば、
-
"Type": "Pass"
:パスステート -
"Type": "Task"
:タスクステート
があります。
詳細はこちらです。
まずは 注文を受けて、在庫数を返す Lambda 関数を作成します。
import json
def lambda_handler(event, context):
product_name = event['ProductName']
color = event['Color']
product_table = {
'Jacket': {
'Red': 3,
'Blue': 5
}
}
return product_table[product_name][color]
その後 Lambda 関数のリソースベースのポリシーに、ステートマシンのロールの ARN を指定し、lambda:InvokeFunction
を許可します。
これで呼び出す Lambda 関数の作成は完了です。
続いて、ステートマシンを作成します。パスステートと違う点は、以下の 4 点です。
-
Type
フィールドをTask
に変更 -
Resource
フィールドで呼び出す Lambda 関数の ARN を指定 -
Parameters
フィールドで Lambda 関数に渡すパラメータを追加 -
Result
フィールドを削除
{
"StartAt": "State",
"States": {
"State": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:GetStoreFunction",
"Parameters": {
"ProductName.$": "$.ProductName",
"Color.$": "$.Color"
},
"ResultPath": "$.Stock",
"OutputPath": "$['ID', 'Stock']",
"End": true
}
}
}
この実行結果は以下のようになります。
Choice ステート
最後にステートの出力結果によって次の処理を分岐させる Choice ステートについて書きます。前回の Lambda 関数は、商品の在庫数を返します。その在庫数によって出力にコメントを含めるように新しいステートを作成してみます。
まずは在庫数が 5 以上であるかどうかを判定する Choice ステートを新たに追加します。
"State2": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.Stock",
"NumericGreaterThanEquals": 5,
"Next": "Sufficient"
}
],
"Default": "Shortage"
}
Variable
フィールドは、 Choice ステートが受け取る入力中のどのキーの値を評価するかについて指定します。ここでは $.Stock
と指定していますので、商品の在庫数を評価することになります。
"NumericGreaterThanEquals": 5
については、受け取った商品の在庫数が 5 個以上であれば "Next" フィールドに記載されているステートに進みます。そうでなければ次の条件に進みます。Default
フィールドはどの条件にも合致しない場合に進むステートを定義します。プログラムではいわゆる else 文に相当します。
次に Sufficient
ステートと Shortage
ステートを記述します。それぞれ新たに出力するキーを追加しています。End
フィールドはこのステートでステートマシンが終了する場合に追加します。
"Sufficient": {
"Type": "Pass",
"Result": "Sufficient stock",
"ResultPath": "$.comment",
"End": true
}
"Shortage": {
"Type": "Pass",
"Result": "Shortage stock",
"ResultPath": "$.comment",
"End": true
}
ステートマシン全体のコードは以下のようになります。最初の Lambda 関数を呼び出す State1 は、State2 に処理が続くため、Next
フィールドを追加しています。
{
"StartAt": "State1",
"States": {
"State1": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:GetStoreFunction",
"Parameters": {
"ProductName.$": "$.ProductName",
"Color.$": "$.Color"
},
"ResultPath": "$.Stock",
"OutputPath": "$['ID', 'Stock']",
"Next": "State2"
},
"State2": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.Stock",
"NumericGreaterThanEquals": 5,
"Next": "Sufficient"
}
],
"Default": "Shortage"
},
"Sufficient": {
"Type": "Pass",
"Result": "Sufficient stock",
"ResultPath": "$.comment",
"End": true
},
"Shortage": {
"Type": "Pass",
"Result": "Shortage stock",
"ResultPath": "$.comment",
"End": true
}
}
}
それぞれの分岐を通るように入力を与えてみます。
以下は在庫数が 5 の商品の入力になります。
上記の入力に対する実行結果は以下のようになります。
以下は在庫数が 3 の商品の入力になります。
上記の入力に対する実行結果は以下のようになります。
参考記事