1

I'm struggling with a simple AWS Lambda function that should publish some messages to a SNS topic.

My email address is subscribed to the topic and the subscription has been confirmed.

The topic is in the same region as my lambda function.

The function is associated to an IAM role that has two policies attached:

  1. the default policy AWSLambdaBasicExecutionRole
  2. another policy that allows the function to write to my SNS topic

Policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "sns:Publish",
            "Resource": "arn:aws:sns:eu-west-1:XXXXXXXXXXXX:YYYYYYYYYYYYYYYYYYY"
        }
    ]
}

Here is my function code, developed on Cloud9.

const AWS = require("aws-sdk");
const sns = new AWS.SNS({region:'eu-west-1'});

exports.handler = async (event, context, callback) => {

    const apiResponse = new Promise((resolve, reject) => {
        setTimeout(() => resolve(['one', 'two', 'three']), 500)
    });

    const messages = await apiResponse;

    const promises = [];

    messages.forEach(txt => {
       promises.push(sns.publish({
           Message: txt,
           Subject: txt,
           TopicArn: 'arn:aws:sns:eu-west-1:xxxxxxxxxxxx:MyWebsiteContactForm'
       }).promise());
    });

    console.log(promises);

    Promise.all(promises,
        function (values) {
            console.log(values);
            callback(null, values);
        },
        function(err) {
            console.error(Error(err));
            callback(Error(err));
        }
    );
};

The result of executing this code is just this expected output, but it never logs anything inside Promise.all().

[ Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> } ]

It's like if Lambda terminates before resolving the promises, but I cannot figure out why. I used Promise.all() as suggested here

Thanks in advance

Geet Choubey
  • 1,069
  • 7
  • 23
leonixyz
  • 1,130
  • 15
  • 28
  • Voted to close as this is a duplicate of 99999 questions on StackOverflow already. Examples: https://stackoverflow.com/questions/31633912/how-to-wait-for-async-actions-inside-aws-lambda, https://stackoverflow.com/questions/54143931/aws-lambda-seems-exiting-before-completion, https://stackoverflow.com/questions/50563173/aws-lambda-ending-early-without-any-explicit-return-or-callback – Thales Minussi Nov 20 '19 at 11:27

1 Answers1

5

Since you are using async keyword on your handler, lambda will await for it and exit. Your async function doesn't contains any await, so it will run immediately.

To fix it, you can:

  1. Remove the async keyword, so Lambda will wait for the calllback call, or;
  2. Use await to your Promise.all(), as shown:
const AWS = require("aws-sdk");
const sns = new AWS.SNS({region:'eu-west-1'});

exports.handler = async (event, context) => {

    const promises = []; 

    ['one', 'two', 'three'].forEach(txt => {
       promises.push(sns.publish({
           Message: txt,
           Subject: txt,
           TopicArn: 'arn:aws:sns:eu-west-1:XXXXXXXXXXXX:YYYYYYYYYYYYYYYYYYY'
       }).promise());
    });

    console.log(promises);

    try {
        let values = await Promise.all(promises);
        // do any transformations here
        return values;
    } catch (err) {
        console.error(err);
        // deal with errors here or re-throw the error if you need that
        // the lambda function results in error too.
        throw(err);
        // Or
        return "something went wrong";
    }
};

For more details see https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-handler.html

Elias Soares
  • 9,884
  • 4
  • 29
  • 59
  • Thanks. I actually use async code in my function, I forgot to remove the async token from the function handler. I also added a fake async code in my question shortly before your reply. Maybe you want to update your answer. Anyway I'm accepting it because your point is correct – leonixyz Nov 20 '19 at 11:03