AWS Step Functionsでタスクタイマーを実装する
AWS Step Functionsを使ったタスクタイマーを10分でプロビジョンするチュートリアルが追加されていたため、実際にやってみました。
ステートマシン
Wait ステートを使って一定時間待機し、Task ステートを使って SNS に通知する Lambda を呼び出します。
最終的には以下のような AWS リソースがプロビジョンされます。
やってみた
以下の手順でサンプルプロジェクトを実行します。
- タスクタイマーをプロビジョン
- SNS の通知先を設定
- 実行
- 後片付け
1. タスクタイマーをプロビジョン
Step Function のダッシュボードから ”Create a state machine”を選択します
Sample Projects -> Task Timer を選択し、"Create Sample Project" ボタンをクリックします。
CloudFormation でリソースが作成される旨のメッセージが表示されます。 "Create Resources" ボタンをクリックします。
リソースの作成が始まります。
リソースの作成が完了すると、ステートマシーンを実行する "New execution" のダイアログが表示されます。
Input の JSON において
topic
はメッセージ送信先 SNS トピックmessage
はトピックに送信するメッセージtimer_seconds
は待機する秒数
を表します。
"Start execution" ボタンをクリックして、ステートマシーンを実行します。
ステートマシーンが実行されます。
ログを確認すると ExecutionStarted
タイプから WaitStateEntered
に遷移し、Input の timer_seconds
で指定した秒数だけ待機したあと(WaitStateExited
)、Lambda 関数を呼び出している(LambdaFunctionStarted)ことがわかります。
待機時間は WaitStateEntered
と WaitStateExited
の Elapsed Time(ms) の差分からわかります。
2. SNS の通知先を設定
このステートマシーンの実行が成功すると、 SNS トピックに通知されるのですが、デフォルトではこのトピックには何も購読していていないため、トピックに送信されたメッセージを受け取れません。 Email など確認しやすいプロトコルで購読しましょう。
3. 実行
トピックを追加したところでもう一度ステートマシーンを実行します。
Step Functions の Dashboard から作成されたステートマシーン(TaskTimerStateMachine-XXX
のような名前)を選択します。
次に "New execution" ボタンからステートマシンを実行します。
Input には 先程と同じ属性の JSON を指定します。
{ "topic": "arn:aws:sns:REGION:123456789012:XXX", "message": "HelloWorld", "timer_seconds": 10 }
”Start Execution” で実行します。
手順2において、トピックを Email-JSON で購読した場合、以下のようなメールが届きます。
{ "Type" : "Notification", "MessageId" : "xxx", "TopicArn" : "arn:aws:sns:ap-northeast-1:123456789012:StepFunctionsSample-TaskTimer-DUMMY", "Message" : "task timer sample project", "Timestamp" : "2018-03-02T21:46:19.798Z", "SignatureVersion" : "1", "Signature" : "DUMMY==", "SigningCertURL" : "https://DUMMY", "UnsubscribeURL" : "https://DUMMY" }
4. 後片付け
このステートマシーンに関するリソースは全て CloudFormation で作成されています。
CloudFormation のスタック一覧に"StepFunctionsSample-TaskTimer-XXX" のスタック名が存在するため、削除しましょう。
プロビジョン内容を確認
プロビジョニングには CloudFormation を利用しています。 作成されたリソースを確認してみましょう。
作成されたリソース
CloudFormation により以下のリソースが作成されます。
- Step Functions : TaskTimerStateMachine
- SNS : SNSTopic
- Lambda : SendToSNS
- IAM Role : LambdaExecutionRole
- IAM Role : StatesExecutionRole
※ 論理ID
Step Functions : TaskTimerStateMachine はメインとなるステートマシーンです。
作成されるステートマシーンの Amazon States Language は以下です。
{ "Comment": "A Task Timer example of the Amazon States Language scheduling a task", "StartAt": "Wait for Timestamp", "States": { "Wait for Timestamp": { "Type": "Wait", "SecondsPath": "$.timer_seconds", "Next": "Send SNS Message" }, "Send SNS Message": { "Type": "Task", "Resource": "arn:aws:lambda:ap-northeast-1:1234567890:function:StepFunctionsSample-TaskTimer-XXX", "Retry" : [ { "ErrorEquals": [ "States.ALL" ], "IntervalSeconds": 1, "MaxAttempts": 3, "BackoffRate": 2.0 } ], "End": true } } }
Task ステートで Lambda を呼び出せるように、StatesExecutionRole ロールをアタッチしています。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "lambda:InvokeFunction" ], "Resource": "*", "Effect": "Allow" } ] }
Lambda 関数 SendToSNS は指定された SNS トピックにメッセージ送信するだけのシンプルなものです。 Input から、メッセージ送信先トピックとメッセージを取得しています。
console.log('Loading function'); const aws = require('aws-sdk'); exports.lambda_handler = (event, context, callback) => { const sns = new aws.SNS(); console.log(`Sending message to SNS topic ${event.topic}`); const messageInfo = { Message: event.message, TopicArn: event.topic }; sns.publish(messageInfo, (err, data) => { if (err) { console.error(err.message); callback(err.message); return; } console.log(data); callback(null); }); };
SNS にメッセージ送信できるように、 LambdaExecutionRole ロールをアタッチしています。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "SNS:Publish" ], "Resource": "arn:aws:sns:ap-northeast-1:123456789012:StepFunctionsSample-TaskTimer-XXX", "Effect": "Allow" } ] }
最後に
Document History によると、このサンプルプロジェクトは既存のチュートリアルをより試しやすいように CloudFormation 化して 2018/01/18 に追加されたようです。
Step Functions はステートを定義するだけではほぼ何もやれず、タスクなどと連携して初めてまともに動作します。
今回のプロジェクトをサクッと起動すると、あとは Lambda 関数をいじるだけでミニマムなオレオレタスクタイマーの完成です。