Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs - Invoke an AWS.Lambda function from within another lambda function

I have the following function which I use to invoke a Lambda function from within my code.

However when I try to use it within a Lambda function, I get the following error:

AWS lambda undefined 0.27s 3 retries] invoke({ FunctionName: 'my-function-name',
  InvocationType: 'RequestResponse',
  LogType: 'Tail',
  Payload: <Buffer > })

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

My function:

'use strict';

var AWS = require("aws-sdk");

var lambda = new AWS.Lambda({
    apiVersion: '2015-03-31',
    endpoint: 'https://lambda.' + process.env.DYNAMODB_REGION + '.amazonaws.com',
    logger: console
});

var lambdaHandler = {};

// @var payload - type:string
// @var functionName - type:string
lambdaHandler.invokeFunction = function (payload, functionName, callback) {

    var params = {
        FunctionName: functionName, /* required */
        InvocationType: "RequestResponse",
        LogType: "Tail",
        Payload: new Buffer(payload, 'utf8')
    };

    var lambdaRequestObj = lambda.invoke(params);

    lambdaRequestObj.on('success', function(response) {
        console.log(response.data);
    });

    lambdaRequestObj.on('error', function(response) {
        console.log(response.error.message);
    });

    lambdaRequestObj.on('complete', function(response) {
        console.log('Complete');
    });

    lambdaRequestObj.send();

    callback();
};

module.exports = lambdaHandler;
like image 838
hyprstack Avatar asked Mar 02 '16 18:03

hyprstack


2 Answers

Invoking a Lambda Function from within another Lambda function is quite simple using the aws-sdk which is available in every Lambda.

I suggest starting with something simple first.
This is the "Hello World" of intra-lambda invocation:

Lambda_A invokes Lambda_B with a Payload containing a single parameter name:'Alex'.
Lambda_B responds with Payload: "Hello Alex".

lambda invoke

First create Lambda_B which expects a name property on the event parameter
and responds to request with "Hello "+event.name:

Lambda_B

exports.handler = function(event, context) {
  console.log('Lambda B Received event:', JSON.stringify(event, null, 2));
  context.succeed('Hello ' + event.name);
};

Ensure that you give Lambda_B and Lambda_A the same role.
E.g: create a role called lambdaexecute which has AWSLambdaRole, AWSLambdaExecute and AWSLambdaBasicExecutionRole (All are required):

lambda-role-for-intra-lambda-execution

Lambda_A

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

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

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

Once you have saved both these Lambda functions, Test run Lambda_A:

lambda invoke-lambda_a-execution-result

Once you have the basic intra-lambdda invocation working you can easily extend it to invoke more elaborate Lambda functions.

The main thing you have to remember is to set the appropriate ARN Role for all functions.

like image 86
nelsonic Avatar answered Oct 24 '22 05:10

nelsonic


As of Dec 3, 2016, you can simply use an AWS Step function to put Lambda function Lambda_B as the sequential step of Lambda_A.

With AWS Step Functions, you define your application as a state machine, a series of steps that together capture the behavior of the app. States in the state machine may be tasks, sequential steps, parallel steps, branching paths (choice), and/or timers (wait). Tasks are units of work, and this work may be performed by AWS Lambda functions, Amazon EC2 instances of any type, containers, or on premises servers—anything that can communicate with the Step Functions API may be assigned a task.

So the following state machine should meet your need.

enter image description here

Here is the code corresponding to the state machine.

{
  "Comment": "A simple example of the Amazon States Language using an AWS Lambda Function",
  "StartAt": "Lambda_A",

  "States": {
    "Lambda_A": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
      "Next": "Lambda_B"
    },
    "Lambda_B":{
      "Type": "Task",
      "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
      "End": true
    }

  }
}

Moreover, you can add much more sophisticated logics in a state machine, such as parallel steps and catch failures. It even logs the details of every single execution which makes debugging a much better experience, especially for lambda functions.

enter image description here

like image 35
C.Lee Avatar answered Oct 24 '22 05:10

C.Lee