I have a simple Lambda function that is supposed to take event data and send a message to an SNS topic.
Runtime is Node.js 8.10.
Here's my Lambda code in its entirety:
const AWS = require("aws-sdk");
exports.handler = async (event) => {
const sns = new AWS.SNS();
const emailBody =
`
New Message
From: ${event.name}
Contact: ${event.contact}
Message: ${event.message}
`;
const snsMessageParams = {
TopicArn: process.env.snsTopicArn,
Message: emailBody
};
sns.publish(snsMessageParams, (err, data) => {
if(err) {
return err;
} else {
return data;
}
});
};
Every time I run the function I always get null in response. No error is returned, but I never get a message in my email from SNS, so there is something wrong here. I just can't figure out what.
I am able to successfully publish a message to my SNS topic from the SNS console, and from the Node SDK on my local computer. These work perfectly. I have checked that the snsTopicArn in my env variables is correct by copying and pasting it directly from my successful local code and the SNS console.
I have an Execution Role on my Lambda function that should allow me to publish to SNS on any topic in my account. I chose the default "SNSPublish" option when configuring the role for Lambda just to test everything. But for reference, here is the policy for my Execution Role:
{
"roleName": <MyRoleName>,
"policies": [
{
"document": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": "arn:aws:sns:*:*:*"
}
]
}
...
}
What is going wrong here? Any help is definitely appreciated.
Returning a valueIf you use the RequestResponse invocation type, such as Synchronous invocation, AWS Lambda returns the result of the Python function call to the client invoking the Lambda function (in the HTTP response to the invocation request, serialized into JSON).
AWS Lambda has the following limitationsThe disk space (ephemeral) is limited to 512 MB. The default deployment package size is 50 MB. The memory range is from 128 to 3008 MB. The maximum execution timeout for a function is 15 minutes*.
To stop it from retrying, you should make sure that any error is handled and you tell Lambda that your invocation finished successfully by returning a non-error (or in Node, calling callback(null, <any>) . To do this you can enclose the entire body of your handler function with a try-catch.
With asynchronous invocation, Lambda queues the event for processing and returns a response immediately. For asynchronous invocation, Lambda handles retries and can send invocation records to a destination. To use your function to process data automatically, add one or more triggers.
Ok, so I figured it out.
There were two issues. The first is that I wasn't using the "callback" parameter that is used implicitly by Lambda for Node. The second was that the function was async by default, so it was expecting an "await" somewhere later. I decided just to remove the "async" and let it run synchronously since it is just a simple function and doesn't need it anyway.
Here is my updated, working code:
const AWS = require("aws-sdk");
const sns = new AWS.SNS();
exports.handler = (event, context, callback) => {
const emailBody =
`
Message
From: ${event.name}
Contact: ${event.contact}
Message: ${event.message}
`;
const snsMessageParams = {
TopicArn: process.env.snsTopicArn,
Message: emailBody
};
sns.publish(snsMessageParams, (err, data) => {
if(err) {
return err;
} else {
callback(null, JSON.stringify(data));
}
});
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With