この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
CX事業本部の佐藤智樹です。先日AWS SAMがStep Functionsをサポートするようになりました!
以前からSAMでStep Functionsを使用できなくは無かったのですが正式サポートされたことでより記述しやすくなりました。今回はSAMでStep Functionsを使い、記述方法や使用する言語などを紹介してみたいと思います。紹介する中で一部のソースは以下の参考URLのものを使用しています。
以前からSAMを使っている方やこれからSAMを使う方でStep Functionsを組み込みたい場合に、大まかに理解するための最初の一歩として読んでいただければ幸いです。
SAMでStep Functionsを利用する場合のパターン
SAMからStep Functionsを扱う場合大まかに2つのパターンが提供されています。1つ目はSAMのリソース記述で使用するYAMLファイルに書くパターンです。2つ目はASL(Amazon States Language.)で記述したStep Functionsのステートマシン構成を呼び出すパターンです。これら2つのパターンについて次節以降で解説していきます。
YAMLテンプレートに記述する場合
YAMLで記述する場合は以下のように記述します。例は処理を受け取って流すだけの状態遷移です。
template.yaml
# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
SimpleStateMachine:
Type: AWS::Serverless::StateMachine
Properties:
Definition:
StartAt: Single State
States:
Single State:
Type: Pass
End: true
Policies:
- CloudWatchPutMetricPolicy: {}
上記のテンプレートをデプロイするとAWSのWebコンソールから以下のステートマシン図と生成されたJSONが確認できます。
Typeの部分にステートの種類を記述します。Type以降の記述はそれぞれTypeによって異なります。現在SAMでは以下全てのStep FunctionsのTypeをサポートしています。
項目名 | 説明 |
---|---|
Task | 単一の作業 |
Choice | 分岐 |
Parallel | 並列処理 |
Wait | 指定時間分の遅延 |
Fail | 実行の失敗 |
Succeed | 実行の成功 |
Pass | 入力を出力に渡す |
Map | 動的並列処理 |
SAMの プルリクを確認したところType:WaitとType:Mapのテストコードは無かったです。しかしTypeをWaitとMapに設定して試したところテンプレート出力から実行まで正常にできました。Mapについては後ほどの記述でも紹介します。
実例(Type:Passの場合)
本項ではTypeをPassとしてType以下のオプションを指定した場合の記述を紹介します。Type以下にYAMLの記述を追加すると定義に変換されます。例えばTypeがPassでResultとResultPathのオプションを加えるときは以下のような記述になります。
template.yaml(Resources配下のみ)
Resources:
SimpleStateMachine:
Type: AWS::Serverless::StateMachine
Properties:
Definition:
StartAt: Single State
States:
Single State:
Type: Pass
Result:
Value: 1
ResultPath: "$.coords"
End: true
Policies:
- CloudWatchPutMetricPolicy: {}
Webコンソールを見ると以下のようなJSONが生成されます。
{
"StartAt": "Single State",
"States": {
"Single State": {
"End": true,
"Result": {
"Value": 1
},
"ResultPath": "$.coords",
"Type": "Pass"
}
}
}
Webコンソールから以下のようにデフォルトの入力で実行すると、正常に動作することが確認できます。
ちなみにですがテンプレートに誤記があった場合はデプロイ時にエラーになります。例えば上記のtemplate.yamlで ResultPath のオプションを ResultPat に書き換えた場合は以下のようなエラーが出ます。
UPDATE_FAILED AWS::StepFunctions::St SimpleStateMachine Invalid State Machine
ateMachine Definition: 'SCHEMA_VA
LIDATION_FAILED: Field
'ResultPah' is not
supported at
/States/Single State'
(Service:
AWSStepFunctions;
Status Code: 400;
Error Code:
InvalidDefinition;
Request ID: xxxxxxxx-x
xxx-xxxx-xxxx-xxxxxxxx
xxxx; Proxy: null)
UPDATE_ROLLBACK_IN_PRO AWS::CloudFormation::S simple-state-machine The following
GRESS tack resource(s) failed to
update:
[SimpleStateMachine].
実例(Type:Mapの場合)
今度はMapの場合を紹介します。Mapの場合もType以下でMapが必要とするオプションを指定するとデプロイ時にテンプレートが生成されます。テンプレートが出力・動作できるか簡単なもので試します。処理としてはイベントのJSONからCommentの配列を受け取ってMap処理の中で3秒Waitする状態遷移を定義します。
template.yaml(Resource配下のみ)
Resources:
SimpleStateMachine:
Type: AWS::Serverless::StateMachine
Properties:
Definition:
StartAt: Single State
States:
Single State:
Type: Map
ItemsPath: "$.Comment"
Iterator:
StartAt: CalcSquare
States:
CalcSquare:
Type: Wait
Seconds: 3
End: true
End: true
Policies:
- CloudWatchPutMetricPolicy: {}
デプロイするとPassの時と同様にJSON定義が作成されます。
{
"StartAt": "Single State",
"States": {
"Single State": {
"End": true,
"ItemsPath": "$.Comment",
"Iterator": {
"StartAt": "CalcSquare",
"States": {
"CalcSquare": {
"End": true,
"Seconds": 3,
"Type": "Wait"
}
}
},
"Type": "Map"
}
}
}
後にWebコンソールから以下のJSONを指定して実行します。配列内部の数字は適当で特に意味は無いです。
{
"Comment": [12,34,56]
}
実行して数秒すると正常に実行できることが確認できます。
YAML記述に関しては以上です。上記の通りYAML定義がJSON定義に変換されているだけなので、作成したいType内部のJSON階層が分かればYAMLで記述できます。
ASLに記述する場合
ASLで記述する場合は、YAMLのテンプレートからASLを呼び出す必要があります。具体的には以下のような記述で呼び出します。ソースは参考URLの「Definition substitutions」の章からソースの一部を抜き出しています。
template.yaml(一部)
…
# 読み込むASLファイルの指定
DefinitionUri: statemachine/stockTrader.asl.json
# ASLに渡すテンプレート内の値を指定
DefinitionSubstitutions:
StockCheckerFunctionArn: !GetAtt StockCheckerFunction.Arn
…
StockCheckerFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: functions/stock-checker/
Handler: app.lambdaHandler
Runtime: nodejs12.x
…
ASL内部では${StockCheckerFunctionArn}と記述することでYAML内のARNを取得することができます。
statemachine/stock_trader.asl.json
{
"Comment": "A state machine that does mock stock trading.",
"StartAt": "Check Stock Value",
"States": {
"Check Stock Value": {
"Type": "Task",
"Resource": "${StockCheckerFunctionArn}",
"Retry": [
{
"ErrorEquals": [
"States.TaskFailed"
],
"IntervalSeconds": 15,
"MaxAttempts": 5,
"BackoffRate": 1.5
}
],
"Next": "Check Stock Value2"
},
…
}
上記の記述では省きましたが、DynamoDBのテーブル名などを渡すことも可能です。Resource指定以外にも、キックするイベントの指定や実行するワークフローのタイプなどを指定できます。詳細はマニュアルや参考URLをご確認ください。
所感
SAMでStep Functionsが対応したことで無理にテンプレートへ組み込む必要がなくなったので、テンプレート内部の記述は減らすことができそうです。SAMでStep Functionsを使う際に参考にしていただければ幸いです。