4

How can I invoke a Lambda function within a Lambda function?

for example,

in function 1, it will be triggered by an API Gateway request and will invoke a second lambda function as an event (InvocationType = Event).

in function 2, it will do an http request to an endpoint.

also, am I going to code in serverless.yml? or code only on index/app/handler.js?

I tried the link here on stackoverflow -> Nodejs - Invoke an AWS.Lambda function from within another lambda function but it's not working.

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

//LAMBDA A
exports.handler = function(event, context) {
  var params = {
    FunctionName: 'Lambda_B', // the lambda function we are going to invoke
    InvocationType: 'RequestResponse',
    LogType: 'Tail',
    Payload: '{ "name" : "Yza" }'
  };

  lambda.invoke(params, function(err, data) {
    if (err) {
      context.fail(err);
    } else {
      context.succeed('Lambda_B said '+ data.Payload);
    }
  })
};

 //LAMBDA B
 exports.handler = function(event, context) {
   console.log('Lambda B Received event:', JSON.stringify(event, null, 2));
   context.succeed('Hello ' + event.name);
 };
Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
kakarotcarrot
  • 41
  • 1
  • 2
  • 4

2 Answers2

5

Your problem is that the lambda.invoke() function is non-blocking, so Lambda_A is finishing its execution before it gets to call Lambda_B. You can use promises to deal with that. If you're using Node.js 8.10+, you can do this:

Lambda_A:

let AWS = require('aws-sdk');
let lambda = new AWS.Lambda();

exports.handler = async (event) => {

    let params = {
      FunctionName: 'Lambda_B',
      InvocationType: 'RequestResponse',
      Payload: '{ "foo" : "bar" }'
    };

    return await lambda.invoke(params, function(err, data) {
      if (err) {
        throw err;
      } else {
        console.log('LambdaB invoked: ' +  data.Payload);
      }
    }).promise();
};

Lambda_B:

exports.handler = async (event) => {
    return {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda_B!'),
    };
};

Response when Lambda_A invoked:

{
  "StatusCode": 200,
  "ExecutedVersion": "$LATEST",
  "Payload": "{\"statusCode\":200,\"body\":\"\\\"Hello from Lambda_B!\\\"\"}"
}

Console output from Lambda_A when invoked:

START RequestId: 016a763d-c79e-4d72-bd44-0aaa89a5efaf Version: $LATEST
2019-02-07T08:07:11.154Z    016a763d-c79e-4d72-bd44-0aaa89a5efaf    LambdaB invoked: {"statusCode":200,"body":"\"Hello from Lambda_B!\""}
END RequestId: 016a763d-c79e-4d72-bd44-0aaa89a5efaf
REPORT RequestId: 016a763d-c79e-4d72-bd44-0aaa89a5efaf  Duration: 717.40 ms Billed Duration: 800 ms     Memory Size: 128 MB Max Memory Used: 30 MB  
Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
  • I'm not very familiar with the serverless project, but I assume the code should just go in handler.js – Daniel Vassallo Feb 07 '19 at 08:34
  • I tried your code but it gives me an error **Serverless Error --------------------------------------- Stack:arn:aws:cloudformation:us-east-1:376014394890:stack/lambda-test-dev/be4e1a40-29c0-11e9-8b17-0a9ef6cbb06a is in UPDATE_IN_PROGRESS state and can not be updated.** – kakarotcarrot Feb 07 '19 at 08:41
1

You can add an user which has policy includes LambdaInvoke then add below configuration

enter code var credentials = {
accessKeyId : process.env.ACCESS_KEY,
secretAccessKey : process.env.SECRET_KEY};   
AWS.config.update(
{
"credentials":credentials,
"region":"eu-central-1"
});
Mesut Yilmes
  • 11
  • 1
  • 4