Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

publish a message to a sns topic from lambda

I have a lambda function that handles a POST request via AWS lambda function. It process the body of the post request and makes a query and returns a response.

MY LAMBDA FUNCTION

const { Pool, Client } = require("pg");
const userName = 'blah';
const hostEndPoint = 'blah';
const databaseType = 'blahblah';
const pwd = 'pass pass';
const portNumber = 5432;
var AWS = require('aws-sdk');

const pool = new Pool({
  user: userName,
  host: hostEndPoint,
  database: databaseType,
  password: pwd,
  port: portNumber
});


exports.handler = async (event) => {
  let body = JSON.parse(event.body);
  let name = body.name;
  let money = body.money;
  let todayDate = new Date();
  var status = 0;
  let text = 'INSERT INTO employee(name, date, salary) VALUES($1, $2, $3) RETURNING *';
  let values = [name, todayDate, money];
  var message = '';
  var status = 0;

  try {
    const res = await pool.query(text, values)
    message += 'successful'
    status = 200;
  } catch (err) {
    message += 'unsuccessful'
    if (err.code === '23505') {
      status = 406;
    }
  }

  var params = {
    Message: 'Hello From Lambda', /* required */
    TopicArn: 'arn:aws:sns:us-east-1:blahblahblah'
  };

  // Create promise and SNS service object
  var publishTextPromise = new AWS.SNS({ apiVersion: '2010-03-31' }).publish(params).promise();

  publishTextPromise.then(
    function (data) {
      console.log(`Message ${params.Message} send sent to the topic ${params.TopicArn}`);
      console.log("MessageID is " + data.MessageId);
    }).catch(
      function (err) {
        console.error(err, err.stack);
      });



  const response = {
    statusCode: status,
    body: JSON.stringify(message),
    headers: {
      "Access-Control-Allow-Origtin": '*'
    }
  };
  return response;
};

My Lambda Resource Policy Looks like this

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "blah-blah-blah-blah",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:blah-blah-blah-blah-blah",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:execute-api:us-east-1:blahblahblahblha:blah/*/POST/"
        }
      }
    }
  ]
}

I have also created a SNS topic. I want to publish a message to the SNS topic if my status is 200. So before I return response. I want to do something like this.

if (status === 200){
  pubish some message to my sns topic
}

I am very new to aws and would love some guidance on how i can publish a message. I feel like i am close. I did come across this topic but it is confusing to me because i am editing code in lambda function so why would i need to require aws-sdk and also they are not talking about changing permission.

Updated code after trying below suggested answer

like image 506
Dinero Avatar asked Nov 25 '25 05:11

Dinero


1 Answers

You can see, return response; line will be run immediately when publish does not finish their task - publish a message to SNS. Because publish, publishTextPromise.then and return just are synchronization codes, it just take one tick (~0,00..1 second) to finish. When the return has been called for the handler function, the function will finish, this mean all doing task will be cancel (include publish process, the process need too many time (~ < 1s and > one tick to finish).

You mix async/await syntax with promise syntax (.then .catch), then process will not work as you think (or want), I recommend just use async/await syntax if you can.

With your code, I guest the publish task will not effect to response, it just try to publish a message to SNS. My suggestion, change

  publishTextPromise.then(
    function (data) {
      console.log(`Message ${params.Message} send sent to the topic ${params.TopicArn}`);
      console.log("MessageID is " + data.MessageId);
    }).catch(
      function (err) {
        console.error(err, err.stack);
      });

to

  await publishTextPromise // wait until the task done
    .then((data) => {
      console.log(`Message ${params.Message} send sent to the topic ${params.TopicArn}`);
      console.log("MessageID is " + data.MessageId);
    })
    .catch((err) => {
      console.error(err, err.stack);
    });

await keyword has been added, and I prefer arrow function syntax

like image 151
hoangdv Avatar answered Nov 27 '25 21:11

hoangdv



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!