こちらは、Fusic Advent Calendar 2019 - Qiita の17日目の記事です。
Lambda Destinations
Introducing AWS Lambda Destinations | AWS Compute Blog
Lambdaの実行結果(成/否)によって次に実行するリソースを指定できるようになりました。
これでLambdaからSDKで各サービスを直接呼び出したりする必要がなくなり、StepFunctionにお世話になる機会も少なるなるのではないでしょうか。
SAM でどう書くのか試してみた
Introducing AWS Lambda Destinations | AWS Compute Blog を参考にサンプルをSAMで動くようにしてみます。
公式ブログのほうではSNSを呼び出してますが、今回は両方Lambdaにします。
SAMのテンプレート設置
samのバージョンは 0.37
です
# ひな形作成
# Which template source would you like to use? : 1 - AWS Quick Start Templates
# 1 - AWS Quick Start Templates : 1 - node0.12.x
$ sam init
各ファイルを編集
hello-world/app.js
を公式ブログを参考に編集
exports.lambdaHandler = function(event, context, callback) {
var event_received_at = new Date().toISOString();
console.log('Event received at: ' + event_received_at);
console.log('Received event:', JSON.stringify(event, null, 2));
if (event.Success) {
console.log("Success");
context.callbackWaitsForEmptyEventLoop = false;
callback(null);
} else {
console.log("Failure");
context.callbackWaitsForEmptyEventLoop = false;
callback(new Error("Failure from event, Success = false, I am failing!"), 'Destination Function Error Thrown');
}
};
exports.successHandler = async (event, context) => {
console.log('successHandler was executed');
};
exports.failHandler = async (event, context) => {
console.log('failHandler was executed');
};
template.yaml
を下記のように変更
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: lambda-distinations
Globals:
Function:
Timeout: 3
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs12.x
Policies:
- LambdaInvokePolicy:
FunctionName: !Ref SuccessFunction
- LambdaInvokePolicy:
FunctionName: !Ref FailFunction
SuccessFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: app.successHandler
Runtime: nodejs12.x
FailFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: app.failHandler
Runtime: nodejs12.x
EventInvokeConfig:
Type: AWS::Lambda::EventInvokeConfig
Properties:
FunctionName: !Ref HelloWorldFunction
Qualifier: "$LATEST"
MaximumEventAgeInSeconds: 600
MaximumRetryAttempts: 0
DestinationConfig:
OnSuccess:
Destination: !GetAtt SuccessFunction.Arn
OnFailure:
Destination: !GetAtt FailFunction.Arn
Outputs:
HelloWorldFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
Description: "Implicit IAM Role created for Hello World function"
Value: !GetAtt HelloWorldFunctionRole.Arn
ビルド・デプロイ
$ sam build
# 初回の場合
$ sam deploy --guided
# 2回目以降
$ sam deploy
実行確認
lambdaを直接実行して確認
# 成功パターン
$ aws lambda invoke --function-name {sam deploy で出力されたLambdaファンクション名} --invocation-type Event --payload '{ "Success": true }' response.json
{
"StatusCode": 202
}
# 失敗パターン
$ aws lambda invoke --function-name {sam deploy で出力されたLambdaファンクション名} --invocation-type Event --payload '{ "Success": false }' response.json
{
"StatusCode": 202
}
どちらもステータスコード 202 が返ってきていますが、これは実行結果ではなく、Lambdaの「実行」することに成功したことの通知です。
あとは、それぞれ Lambda関数の管理画面の「モニタリング > クラウドウォッチログ」でそれぞれ該当時間に呼び出されていることを確認できます。
詰まった点・分かっていない点
詰まった点
- 大元のLambdaにDestination先のLambdaを実行できるRoleを加えなきゃいけない点
- SAMでどうやって書くのか最初分からず少し詰まりました。
分かってない点
- API Gateway からの呼び出した場合のDestination先の実行方法
- まだあまり時間かけてないのですがサンプルコードにAPI Gatewayくっつけてやってみたけど思った挙動にはなりませんでした。
- もしわかる方がいらしゃったらコメントいただけると嬉しいです!