Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to invoke AWS Lambda synchronously from node.js?

I'm trying to run a specific function from an existing app via AWS Lambda, using the JS SDK to invoke Lambda from my node.js app. Since I'm overwriting the existing function, I'll have to keep its basic structure, which is this:

overwrittenFunction = function(params) {
    //get some data
    return dataArray;
}

..so I need to end up with an array that I can return, if I'm looking to keep the underlying structure of the lib I use the same. Now as far as I know, Lambda invocations are asynchronous, and it's therefore not possible to do something like this:

overwrittenFunction = function(params) {
    lambda.invoke(params, callback);
    function callback(err,data) {
        var dataArray = data;
    }
    return dataArray;
}

(I've also tried similar things with promises and async/await).

afaik I have two options now: somehow figure out how to do a synchronous Lambda invocation, or modify my library / existing app (which I would rather not do if possible).

Is there any way to do such a thing and somehow return the value I'm expecting?

(I'm using node v8.9.4)

like image 294
wagshadow Avatar asked Jan 17 '18 16:01

wagshadow


People also ask

How do you call Lambda function synchronously?

To invoke a function synchronously with the AWS CLI, use the invoke command. The cli-binary-format option is required if you're using AWS CLI version 2. To make this the default setting, run aws configure set cli-binary-format raw-in-base64-out . For more information, see AWS CLI supported global command line options.

Does API gateway invoke Lambda synchronously?

Lambda can be invoked synchronously (1) via AWS Console/CLI/SDK, (2) API Gateway, and (3) Application Load Balancer (ALB).

Is AWS Lambda synchronous or asynchronous?

Lambda functions can be invoked either synchronously or asynchronously, depending upon the trigger. In synchronous invocations, the caller waits for the function to complete execution and the function can return a value.


2 Answers

Lambda and async/await are a bit tricky, but the following is working for me (in production):

const lambdaParams = {
    FunctionName: 'my-lambda',
    // RequestResponse is important here. Without it we won't get the result Payload
    InvocationType: 'RequestResponse',
    LogType: 'Tail', // other option is 'None'
    Payload: {
        something: 'anything'
    }
};

// Lambda expects the Payload to be stringified JSON
lambdaParams.Payload = JSON.stringify(lambdaParams.Payload);

const lambdaResult = await lambda.invoke(lambdaParams).promise();

logger.debug('Lambda completed, result: ', lambdaResult.Payload);

const resultObject = JSON.parse(lambdaResult.Payload)

Wrap it all up in a try/catch and go to town.

like image 76
slaughtr Avatar answered Nov 15 '22 09:11

slaughtr


You can use async await but as the AWS SDK uses node callback pattern you'll need to wrap the function with the built-in promisify.

const promisify = require('utils').promisify 
const aws = require('aws-sdk');

const lambda = aws.Lambda();
const invoke = promisify(lambda.invoke);

async function invocation(params) {
  try {
    return await invoke(params);
  } catch (err) {
    throw new Error('Somethings up');
  }
}

const data = invocation(params);
like image 25
sidhuko Avatar answered Nov 15 '22 09:11

sidhuko