この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
AWS re:Invent 2016で発表された、ビジュアルワークフローを用いて分散アプリケーションを構築するサービス『AWS Step Functions』。
今回は Choice ステートを使って条件に応じて分岐させる方法を紹介します。
なお Step Functions が対応しているステートは以下です。
- Task
- Wait
- Pass
- Succeed
- Fail
- Choice
- Parallel
サンプル 1 : Choice ステートを使った条件分岐
Step Functions の "Choice State" ブループリントです。
FirstState タスク のアウトプットをもとに ChoiceState の Choice によって分岐先を決定します。
具体的にはアウトプットの JSON の foo
属性の値によって
- 整数の 1 なら "FirstMatchState"
- 整数の 2 なら "SecondMatchState"
- それ以外は "DefaultState"
に分岐します。
対応する Amazon States Language は以下です。
ブループリントの Amazon States Language
{
"Comment": "An example of the Amazon States Language using a choice state.",
"StartAt": "FirstState",
"States": {
"FirstState": {
"Type": "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Next": "ChoiceState"
},
"ChoiceState": {
"Type" : "Choice",
"Choices": [
{
"Variable": "$.foo",
"NumericEquals": 1,
"Next": "FirstMatchState"
},
{
"Variable": "$.foo",
"NumericEquals": 2,
"Next": "SecondMatchState"
}
],
"Default": "DefaultState"
},
"FirstMatchState": {
"Type" : "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:OnFirstMatch",
"Next": "NextState"
},
"SecondMatchState": {
"Type" : "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:OnSecondMatch",
"Next": "NextState"
},
"DefaultState": {
"Type": "Fail",
"Cause": "No Matches!"
},
"NextState": {
"Type": "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"End": true
}
}
}
Lambda 関数の実装
FirstState タスクの Lambda 関数に { "foo" : 0 OR 1 OR 2 のいずれか}"
を返すものを用意します。
import random
def lambda_handler(event, context):
return {"foo":random.choice([0,1,2])}
また
- FirstMatchState
- SecondMatchState
の Lambda 関数も、各 Lambda 関数を経由したことがわかるように input に経由した関数名を含めるように一部加工します。
FirstMatchState Lambda Function
FirstMatchState
def lambda_handler(event, context):
event["func_name"] = "onFirstMatch"
return event
SecondMatchState Lambda Function
SecondMatchState
def lambda_handler(event, context):
event["func_name"] = "onSecondMatch"
return event
(修正版)ブループリントの Amazon States Language
Task のリソース ARN を書き換えたのが次の Amazon States Language です。
NextState ステートは Lambda 関数の実装をサボり、input をそのまま output する Pass タイプにしています。
{
"Comment": "An example of the Amazon States Language using a choice state.",
"StartAt": "FirstState",
"States": {
"FirstState": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:12345:function:OnFirstState",
"Next": "ChoiceState"
},
"ChoiceState": {
"Type" : "Choice",
"Choices": [
{
"Variable": "$.foo",
"NumericEquals": 1,
"Next": "FirstMatchState"
},
{
"Variable": "$.foo",
"NumericEquals": 2,
"Next": "SecondMatchState"
}
],
"Default": "DefaultState"
},
"FirstMatchState": {
"Type" : "Task",
"Resource": "arn:aws:lambda:eu-west-1:12345:function:OnFirstMatch",
"Next": "NextState"
},
"SecondMatchState": {
"Type" : "Task",
"Resource": "arn:aws:lambda:eu-west-1:12345:function:OnSecondMatch",
"Next": "NextState"
},
"DefaultState": {
"Type": "Fail",
"Cause": "No Matches!"
},
"NextState": {
"Type": "Pass",
"End": true
}
}
}
実行例
ステートマシン作成後は "New execution" から実行します。
FirstState ステートは Input に依存しないため、デフォルトのインプットのままステートマシンを実行します。
実行例1
FirstState が
{"foo": 2}
というアウトプットだったため、ChoiceState から SecondMatchState に遷移し、
{"func_name": "onSecondtMatch", "foo": 2}
をアウトプットしています。
実行例2
FirstState が
{"foo": 0}
というアウトプットだったため、ChoiceState から DefaultState に遷移し、Fail タイプによる例外が発生しています。
Choice ステートを使った条件分岐 : サンプル2
Step Functions の Developer マニュアルの Choice ステートのサンプルです。
Start 時のインプットをもとに ChoiceStateX の Choice によって分岐先を決定します。
具体的にはインプットの JSON の type
属性 と value
属性の値によって
- type が "Public" なら "FirstMatchState"
- type が "Private" なら
- value == 0 なら ValueIsZero
- 20 <= value < 30 なら ValueInTwenties
- それ以外は "DefaultState"
に分岐します。
対応する Amazon States Language は以下です。
ブループリントの Amazon States Language
{
"Comment": "Choice",
"StartAt": "ChoiceStateX",
"States": {
"ChoiceStateX": {
"Type": "Choice",
"Choices": [
{
"Not": {
"Variable": "$.type",
"StringEquals": "Private"
},
"Next": "Public"
},
{
"Variable": "$.value",
"NumericEquals": 0,
"Next": "ValueIsZero"
},
{
"And": [
{
"Variable": "$.value",
"NumericGreaterThanEquals": 20
},
{
"Variable": "$.value",
"NumericLessThan": 30
}
],
"Next": "ValueInTwenties"
}
],
"Default": "DefaultState"
},
"Public": {
"Type": "Pass",
"Result": "Public",
"End": true
},
"ValueIsZero": {
"Type": "Pass",
"Result": "ValueIsZero",
"End": true
},
"ValueInTwenties": {
"Type": "Pass",
"Result": "ValueInTwenties",
"End": true
},
"DefaultState": {
"Type": "Fail",
"Cause": "No Matches!"
}
}
}
「20台の整数であること」はオペレーター
- And
- NumericGreaterThanEquals
- NumericLessThan
を組み合わせて「20以上かつ30未満」というようにして実現しています。
{
"And": [
{
"Variable": "$.value",
"NumericGreaterThanEquals": 20
},
{
"Variable": "$.value",
"NumericLessThan": 30
}
],
"Next": "ValueInTwenties"
}
実行例
ステートマシン作成後は "New execution" から実行します。 うまく分岐するようにインプットを用意します。
実行例1
input.json
{
"type": "Private",
"value": 20
}
というインプットに対しては ChoiceStateX から ValueInTwenties に遷移して
"ValueInTwenties"
をアウトプットしています。
実行例2
input.json
{
"type": "Public",
"value": 20
}
というインプットに対して ChoiceStateX から Public に遷移して
"Public"
をアウトプットしています。
Choice タイプが対応しているオペレーター
今回のサンプルでは、条件に一致されるためのオペレーターとして
- NumericEquals
- NumericGreaterThanEquals
- And
- StringEquals
等を利用しました。
現時点では、以下のオペレーターに対応しています。
- StringEquals
- StringLessThan
- StringGreaterThan
- StringLessThanEquals
- StringGreaterThanEquals
- NumericEquals
- NumericLessThan
- NumericGreaterThan
- NumericLessThanEquals
- NumericGreaterThanEquals
- BooleanEquals
- TimestampEquals
- TimestampLessThan
- TimestampGreaterThan
- TimestampLessThanEquals
- TimestampGreaterThanEquals
- And
- Or
- Not
まとめ
今回は Choice ステートによる条件分岐方法を紹介しました。
String/Numeric/Boolean/Timestamp の比較や And/Or の組み合わせも可能なため、Amazon States Language だけでも複雑な条件を記述することができます。 一方で、ステートマシンの記述言語は JSON ベースなため、なんでも JSON で記述すると、メンテナンスが大変になります。
JSON と Lambda タスクで上手くバランスを取りながらステートを記述することが求められます。