Reputation: 1160
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
Upvotes: 2
Views: 5942
Reputation: 16127
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
Upvotes: 5
Reputation: 13092
I assume your architecture looks something like this:
An API-Gateway accepts the request and invokes the lambda function you have shown us. That Lambda function the connects to a database and inserts a record. You now want this Lambda function to also publish to a SNS topic.
To achieve this, you need to do two things:
Step 1 should come first and for this you need to edit the IAM Role that your function is using. The IAM Role specifies, which AWS services this lambda function is allowed to call. The Lambda Resource Policy you've shown us, grants the API Gateway the permissions to invoke/call your Lambda function - that has no influence on what the function can do.
If this is just for testing you can locate the IAM Role of the function inside Identity and Access Management and attach the AmazonSNSFullAccess
policy - do not do this for any kind of production environment, this grants a lot more permissinons than necessary (In Production you'd add a custom policy that allows the action sns:Publish
only on your topic).
Now your function has permissions to publish messages to your topic.
Step 2 means you need to edit your code. Importing the AWS SDK as described in the documentation you linked is necessary, because you want your code to interface with AWS services - for that you need the SDK. The other steps in that documentation seem reasonable except for setting the region, you don't need to do that if your topic lives in the same AWS region as your lambda function.
Some additional observations/suggestions:
Access-Control-Allow-Origtin
- it should be Origin. You can also set this at the API Gateway, this way your function doesn't have to take care of it.Upvotes: 3