Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

invoking AWS lambda function, wait until completion

I am using the following nodeJS lambda function to invoke a java lambda function.

var AWS = require('aws-sdk');
   
    var lambda = new AWS.Lambda({httpOptions:{timeout: 300000}});
    
    exports.handler = function(event, context) {
      var params = {
          
        FunctionName: 'sensi', // the lambda function we are going to invoke
        InvocationType: 'RequestResponse',
        Payload: '{"input":"alum_ROW,10,-1"}',
        LogType:'Tail'
      };
    
      lambda.invoke(params, function(err, data) {
        if (err) {
          context.fail(err);
        } else {
          context.succeed(data.LogResult);
        }
      })
    };

The execution of the caller lambda is successful and the function I am calling is getting executed correctly. The problem is the caller lambda ends before the called lambda function ends and I got null as data.payload and hexadecimal characters as data.LogResult. obviously what is needed is to wait until the called lambda is finished.

below the lambda i am trying to call:

public boolean run(String input ){

        String [] inputs= input.split(",");

        String systemId=inputs[0];
        int iterations=Integer.parseInt(inputs[1]);
        int output=Integer.parseInt(inputs[2]);

       //custom code

       return true;
    }

This function is inside class Launchers.Launcher and therefore the sensi lambda function has handler Launchers.Launcher::run

EDIT: SOLUTION PROVIDED BY @JOHN

adding: context.callbackWaitsForEmptyEventLoop = false;

like image 765
Francois Saab Avatar asked Mar 04 '26 18:03

Francois Saab


1 Answers

Compiling your question, (correct me if I'm wrong and I'll edit the answer):

  1. You have a lambda X, that calls lambda Y.
  2. Lambda Y returns some value Z for each execution.
  3. You want lambda X to receive the value Z, when calling lambda Y.
    1. You want the callback to be called with the return value Z, after lambda Y ends execution.

According to your params:

  1. You request a synchronous execution, by specifying RequestResponse, which is good for this purpose (receiving the result of lambda Y).
  2. You request the last 4KB of logs produced by lambda Y - by specifying Tail.

According to the documentation and given I was right in compiling your question, the LogResult is not what you're looking for, but the Payload is.

The following is from the Response Elements section:

LogResult

It is the base64-encoded logs for the Lambda function invocation. This is present only if the invocation type is RequestResponse and the logs were requested.

The response returns the following as the HTTP body.


Payload

It is the JSON representation of the object returned by the Lambda function. This is present only if the invocation type is RequestResponse.

API_Invoke Reference


Edit (added example):

I've created two lambdas, according to my above description, X and Y.

Here's X's code:

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

exports.handler = (event, context, callback) => {
    context.callbackWaitsForEmptyEventLoop = false;

    const params = {
        FunctionName: "Y", 
        InvocationType: "RequestResponse", 
        LogType: "Tail", 
        Payload: '{"name":"jonathan"}'
    };

    lambda.invoke(params, (err, res) => {
        if (err) {
            callback(err);
        }

        console.log(JSON.stringify(res));

        callback(null, res.Payload);
    });
};

Here's Y's code:

exports.handler = (event, context, callback) => {
    context.callbackWaitsForEmptyEventLoop = false;
    console.log(JSON.stringify(event));

    setTimeout(() => {
       callback(null, "My name is Jonathan"); 
    }, 1000 * 10); // 10 seconds delay
};
  • What you're trying to achieve is do-able.
  • Lambda X invokes synchronously Lambda Y and waits for its response (waits 10 seconds).
  • You were accessing the wrong property of the callback input, you accessed the LogResult property instead of the Payload property.

Here's a log of X's arbitrary execution:

START RequestId: a6a98e8d-31b9-11e7-aba1-d5d86092115f Version: $LATEST
2017-05-05T17:38:40.805Z    a6a98e8d-31b9-11e7-aba1-d5d86092115f    {"StatusCode":200,"LogResult":"U1RBUlQgUmVxdWVzdElkOiBhNzVmMjIzZi0zMWI5LTExZTctYmRmYy0xMzJkMDc0Zjc3YzggVmVyc2lvbjogJExBVEVTVAoyMDE3LTA1LTA1VDE3OjM4OjMwLjY4NloJYTc1ZjIyM2YtMzFiOS0xMWU3LWJkZmMtMTMyZDA3NGY3N2M4CXsibmFtZSI6ImpvbmF0aGFuIn0KRU5EIFJlcXVlc3RJZDogYTc1ZjIyM2YtMzFiOS0xMWU3LWJkZmMtMTMyZDA3NGY3N2M4ClJFUE9SVCBSZXF1ZXN0SWQ6IGE3NWYyMjNmLTMxYjktMTFlNy1iZGZjLTEzMmQwNzRmNzdjOAlEdXJhdGlvbjogMTAwMjcuMjkgbXMJQmlsbGVkIER1cmF0aW9uOiAxMDEwMCBtcyAJTWVtb3J5IFNpemU6IDEyOCBNQglNYXggTWVtb3J5IFVzZWQ6IDE3IE1CCQo=","Payload":"\"My name is Jonathan\""}
END RequestId: a6a98e8d-31b9-11e7-aba1-d5d86092115f
REPORT RequestId: a6a98e8d-31b9-11e7-aba1-d5d86092115f  Duration: 11233.34 ms   Billed Duration: 11300 ms   Memory Size: 128 MB Max Memory Used: 30 MB  

Note the structure of the callback's input:

{
  "StatusCode": 200,

  // this is the logs that Y's printed to the "console" (base64 encoded)
  "LogResult": "U1RBUlQgUmVxdWVzdElkOiBhNzVmMjIzZi0zMWI5LTExZTctYmRmYy0xMzJkMDc0Zjc3YzggVmVyc2lvbjogJExBVEVTVAoyMDE3LTA1LTA1VDE3OjM4OjMwLjY4NloJYTc1ZjIyM2YtMzFiOS0xMWU3LWJkZmMtMTMyZDA3NGY3N2M4CXsibmFtZSI6ImpvbmF0aGFuIn0KRU5EIFJlcXVlc3RJZDogYTc1ZjIyM2YtMzFiOS0xMWU3LWJkZmMtMTMyZDA3NGY3N2M4ClJFUE9SVCBSZXF1ZXN0SWQ6IGE3NWYyMjNmLTMxYjktMTFlNy1iZGZjLTEzMmQwNzRmNzdjOAlEdXJhdGlvbjogMTAwMjcuMjkgbXMJQmlsbGVkIER1cmF0aW9uOiAxMDEwMCBtcyAJTWVtb3J5IFNpemU6IDEyOCBNQglNYXggTWVtb3J5IFVzZWQ6IDE3IE1CCQo=",


  "Payload": "\"My name is Jonathan\"" // <--- this is the returned value
}

Hopefully this answers your question.

like image 151
johni Avatar answered Mar 06 '26 08:03

johni



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!