web-dev-qa-db-ja.com

別のラムダからawsラムダを非同期で呼び出す

別のラムダからawsラムダを非同期で呼び出す必要があります。同期呼び出しの作業コードがあります。

exports.handler = (event, context, callback) => {
    var aws = require('aws-sdk');
    var lambda = new aws.Lambda({
        region: 'myregion' //change to your region
    });
    console.log("lambda invoke started");
    lambda.invoke({
        FunctionName: 'testLambda',
        Payload: JSON.stringify(event, null, 2) // pass params
    }, function (error, data) {
        if (error) {
            console.log("error");
            callback(null, 'hello world');
        }
        else {
            console.log("lambda invoke end");
            callback(null, 'hello world');
        }
    });
}

しかし、私の場合、「testLambda」は時間がかかる関数です。 「testLambda」関数を呼び出した直後に終了する必要があるためです。次に、コードは次のように更新されます

exports.handler = (event, context, callback) => {
    var aws = require('aws-sdk');
    var lambda = new aws.Lambda({
        region: 'myregion' //change to your region
    });
    console.log("lambda invoke started");
    lambda.invoke({
        FunctionName: 'testLambda',
        Payload: JSON.stringify(event, null, 2) // pass params
    });
    console.log("lambda invoke end");
    callback(null, 'hello world');
}

それはメッセージを正しく返します。しかし、私の 'testLambda'関数は呼び出されません(テストラムダのクラウド監視ログは生成されません)。このコードに関連する問題は何ですか。

17
Abdul Manaf

Lambda invoke()のドキュメント に従って、デフォルトでLambda関数がRequestResponse呼び出しタイプを使用して呼び出されることがわかります。関数を非同期で呼び出すには、次のようにEvent呼び出しタイプを指定する必要があります。

lambda.invoke({
    FunctionName: 'testLambda',
    InvocationType: 'Event',
    Payload: JSON.stringify(event, null, 2)
},function(err,data){});
16
Mark B

AWS Lambdaで現在最新の node.js 8.1 バージョンを使用していました。
2番目のラムダは、使用するまで実行されませんでした(そして、コールバック関数は呼び出されませんでした)。 非同期/待機 機構。
したがって、ハンドラー関数は非同期である必要があり、 'lambda.invoke'呼び出しは Promise でラップされます。

これが私の作業コードです:

function invokeLambda2(payload) {
    const params = {
        FunctionName: 'TestLambda2',
        InvocationType: 'Event',
        Payload: JSON.stringify(payload)
    };

    return new Promise((resolve, reject) => {

        lambda.invoke(params, (err,data) => {
            if (err) {
                console.log(err, err.stack);
                reject(err);
            }
            else {
                console.log(data);
                resolve(data);
            }
        });     
    });
}


exports.handler = async (event, context) => {
    const payload = {
        'message': 'hello from lambda1'
    };
    await invokeLambda2(payload);
    context.done();
};

ハンドラーは、2番目のラムダが終了するのを待たないことに注意してください。トリガーされ、コールバック関数が呼び出されるだけです。

ハンドラー内からPromiseを返すこともできます。2番目の関数でawaitを使用する必要はありません。

Promiseとasync/awaitを使用する場合、以下を除いてインポートは必要ありません。

const AWS = require('aws-sdk');
const lambda = new AWS.Lambda();
10
ronginat

それがExpress.jsでの使用方法です


var express = require("express");
var router = express.Router();

const asyncMiddleware = fn =>
  (req, res, next) => {
    Promise.resolve(fn(req, res, next))
      .catch(next);
  };

const invokeLambda = async (params) => {
  const data = await lambda.invoke(params).promise();
  return JSON.parse(data.Payload);
}


router.get('/test', asyncMiddleware(async (req, res, next) => {
  const params = {
    FunctionName: SOMETHING_LAMBDA_ARN,
    Payload: JSON.stringify(req.body)
  };
  const result = await invokeLambda(params);
  res.send(result);
}));

2
MiaeKim

上記と同様の解決策が必要でした。 lambda.invokeで複数のラムダ関数を使用する場合、ステップ関数が推奨されますが、次のコードスニペットを使用して、ベースのラムダ関数から他の2つのラムダ関数を非同期的に呼び出します。

var AWS = require('aws-sdk');
AWS.config.region = 'ap-southeast-1';
var lambda = new AWS.Lambda();

exports.handler = async(event) => {
   await invokeLambda(event);

   const response = {
        statusCode: 200,
        body: JSON.stringify('success'),
   };

   return response;
};

//Invoke Multiple Lambda functions
  async function invokeLambda(event) {
    const function1 = {
        FunctionName: 'dev-test-async-lambda-1',
        InvocationType: 'Event',
        Payload: JSON.stringify(event)
    };

    const function2 = {
        FunctionName: 'dev-test-async-lambda-2',
        InvocationType: 'Event',
        Payload: JSON.stringify(event)
    };

    await lambda.invoke(function1).promise();
    await lambda.invoke(function2).promise();

}

これをより効率的に改善できるか、それとも有用かを教えてください。

0
Cnf271