なぜlambdaからlambdaを呼び出すのか
これは、実際に同じ状況になってみると、わかりやすいと思います。
exports.handler = function(event, context) {
非同期処理.then((param) => {
paramを使用した処理
結果を返す
}
}
こうした処理を行う際に、非同期処理の終了を待ち、その結果から、処理をした内容を返して欲しかったのですが、lambdaでは、親プロセスが終了した時点で、子プロセスも強制的に閉じられてしまうらしく、paramが返ってくる前に処理が終わってしまっていました。
例えば、このコード。
通常の実行であれば、ABCが順番に出力されますが、lambdaで実行した場合には、Aしか出力されずに処理が終了してしまいます。
'use strict';
console.log('A');
setTimeout(() => {
console.log('B');
setTimeout(() => {
console.log('C');
}, 2000);
}, 1000);
それを解決するためにとった策が、lambdaからlambdaを呼ぶことです。
lambdaで関数を作成する
一緒にサンプルを作成していきましょう。
まず、呼び出される側のlambdaを作成します。
今回は、「Hello from Lambda」を出力するlambda関数を作成します。
まず、以下のリンクからAWSマネジメントコンソールへアクセスします。
https://aws.amazon.com/jp/console/
サービス一覧からLambdaを選択し、
関数メニュー から 関数の作成を押下します。
設定は、以下の通りです。
一応、文字でも書いておきます。
関数名: sample
ランタイム : Node.js 10.x
アクセス権限 実行ロール : 基本的な Lambda アクセス権限で新しいロールを作成
そして、右下にある「関数の作成」ボタンを押下すれば、関数が作成されます。
※ 少し時間がかかります。10~15秒くらいかな
最初は、以下のような設定になっていると思います。
もし、なっていない方のために貼っておきます。
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
どのような出力になるか確認してみます。
右上の「テストボタン」を押下し、
テストイベント名に「test」と入力し、保存します。
保存ができたら、もう一度「テスト」ボタンを押下し、実行します。
結果は、以下の通り。
{
"statusCode": 200,
"body": ""Hello from Lambda!""
}
これで、Lambda関数の完成です。
今回は、lambdaからlambdaを呼び出すサンプルの作成が目的なので、関数の内容は編集しません。
lambdaからlambdaを呼び出す
まず、先ほどと同じ手順で新たにlambda関数を作成します。
関数名は、「callSample」としましょう。
関数が作成できたら、以下の内容をindex.jsに張り付けます。
const AWS = require('aws-sdk');
const lambda = new AWS.Lambda();
exports.handler = function(event, context) {
const params = {
FunctionName: 'sample',
InvocationType: 'RequestResponse',
};
lambda.invoke(params, function(err, data) {
if (err) {
context.fail(err);
} else {
context.succeed(data);
}
});
};
このコードで、lambda関数であるsampleを呼び出そうとしています。
実行できるか試してみましょう。
テストを実行します。
"errorType": "AccessDeniedException",
が返されるはずです。
これは、権限が足りていないことを表しています。
もっと詳しく言うと、「callSample」のlambda関数に他のlambda関数(sample)を呼び出すための権限がないということです。
他のlambda関数を呼び出すための権限ロールを作成する
権限ロールを作成するにはIAMを使用します。
マネジメントコンソールからIAMと検索し、開いてみましょう。
左側のメニューからロールを選択し、ロールの作成を押下します。
AWSサービスを選択し、
権限を利用するサービスにLambdaを指定し、
「次のステップ:アクセス権限」を押下します。
ポリシーのフィルタからlambdaと検索し、「AWSLambdaRole」ポリシーをアタッチします。
設定出来たら、「次のステップ:タグ」を押下します。
タグは、今回利用しないので、「次のステップ:確認」を押下。
ロール名に「lambda_execute」と入力し、ロールの作成を押下します。
」
これで、権限ロールが作成されました。
権限を与え、実行してみる
先程作成したLambda関数に戻ります。
(callSample関数の方)
下へスクロールすると、実行ロールという項目があるため、
「既存のロールを使用する」を選択し、
既存のロールに「lambda_execute」を選択し、保存します。
もう一度、テストを実行してみましょう。
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST",
"Payload": "{"statusCode":200,"body":"\"Hello from Lambda!\""}"
}
という結果が返れば、成功です。
もし、
Task timed out after 3.00 seconds
というエラーが返る方いれば、基本設定のタイムアウトを変更してみて下さい。
関連書籍