2
votes

I am using AWS step function to invoke lambda function like this.

 return stepfunctions.startExecution(params).promise().then((result) => {
      console.log(result);
      console.log(result.output);
      return result;
    })

And result is

{ executionArn: 'arn:aws:states:eu-west-2:695510026694:...........:7c197be6-9dca-4bef-966a-ae9ad327bf23',
  startDate: 2018-07-09T07:35:14.930Z }

But i want the result as output of final lambda function

I am going through https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/StepFunctions.html#sendTaskSuccess-property

There are multible function there i am confused which one could be used to get back result of final lambda function.

Same question is there on stackoverflow Api gateway get output results from step function? i dont want to call any function periodically and keep checking status.Even if i use DescribeExecution function periodically i will only get the status of execution but not the result i wanted. Is there any way or any function which returns promise and is resolved once all the lambda has executed and give back the result

3

3 Answers

3
votes

You can't get back a result from a step function execution in a synchronous way.

Instead of polling the result of the step function on completion send a result to an SNS topic or SQS queue for further processing in the final lambda function or model the whole process in the step function state machine.

3
votes

After doing some study and looking at various tutorial i realized that this stackoverflow answer Api gateway get output results from step function? gives a easier approach to solve the problem and get final result from step function, yes i am not sure about another approach and how to implement any new answer is always appreciated

This is my code to implement the same approach this might help someone.

 // in function first start step function execution using startExecution()
var params = {
        stateMachineArn: 'some correct ARN',
        input: JSON.stringify(body)
      };
return stepfunctions.startExecution(params).promise().then((result) => {

        var paramsStatus = {
          executionArn: result.executionArn
        };

        var finalResponse =  new Promise(function(resolve,reject){
      var checkStatusOfStepFunction =  setInterval(function(){
//on regular interval keep checking status of step function
            stepfunctions.describeExecution(paramsStatus, function(err, data) {
              console.log('called describeExecution:', data.status);
              if (err){
                clearInterval(checkStatusOfStepFunction);
                 reject(err); 

              }
              else {
                if(data.status !== 'RUNNING'){
// once we get status is not running means step function execution is now finished and we get result as data.output
                  clearInterval(checkStatusOfStepFunction);

                   resolve(data.output);
                }  

              }
            }); 
          },200);
        });


        return finalResponse



      })
1
votes

To be able to get the result of step function (example: combined gateway & step function). You need to:

1. startExecution,
2. wait for your state machine to finish the execution (to be sure make wait equivalent to timeout of your state machine => wait = TimeoutSeconds of your state machine)
3. call describeExecution with the receive executionArn from startExecution.

Note that startExecution is an async function and it's not waiting for the result.

In my case, I'm using Lambda named init to execute the 3 discussed steps:

Code lambda Init:

const AWS = require('aws-sdk')

exports.handler = async (event) => {

    const stepFunctions = new AWS.StepFunctions();
    const reqBody = event.body || {};

    const params = {
        stateMachineArn: process.en.stateMachineArn,
        input: JSON.stringify(reqBody)
    }

    return stepFunctions.startExecution(params).promise()
        .then(async data => {
            console.log('==> data: ', data)
            await new Promise(r => setTimeout(r, 6000));
            return stepFunctions.describeExecution({ executionArn: data.executionArn }).promise();
        })
        .then(result => {
           return {
                statusCode: 200,
                message: JSON.stringify(result)
            }
        })
        .catch(err => {
            console.error('err: ', err)
            return {
                statusCode: 500,
                message: JSON.stringify({ message: 'facing error' })
            }
        })
}

Code stateMachine Make sure that in your statemachine your returning "ResultPath".

{
  "Comment": "Annoucement validation",
  "StartAt": "contact-validation",
  "Version": "1.0",
  "TimeoutSeconds": 5,
  "States": {
     "contact-validation": {
          "Type": "Task",
          "Resource": "arn:aws:xxxxxxx:function:scam-detection-dev-contact", 
          "ResultPath": "$.res",
          "Next": "WaitSeconds"
    }, 
     "WaitSeconds": { 
       "Type": "Wait",
        "Seconds": 1,
        "Next": "Result"     
     },
    "Result": {
      "Type": "Pass",
       "ResultPath": "$.res",
      "End": true
    }
  }
}