I have a use case of pushing SNS notifications from Amazon lambda. I have written the following code, with the IAM role having the permission to invoke SNS. Even with the Kenesis trigger, this Lambda function is unable to send any notification to SNS. I confirmed this by, subscribing my email id to the SNS.
[EDIT]: Just a follow up question. I now need to query DynamoDB and based on the output, need to call different end point of SNS. Now, when I query DynamoDB, the execution stops after DynamoDB query and not even progressing for SNS checks.
Following is my lambda function code.
console.log('Loading function');
var AWS = require('aws-sdk');
exports.handler = function(event, context) {
event.Records.forEach(function(record) {
//var payload = new Buffer(record.kinesis.data, 'base64').toString('ascii');
var payload = record.kinesis.data;
console.log('Decoded payload:', payload);
var dynamodb = new AWS.DynamoDB();
var dynamodb_params = {
Key: {
dataSource: {
S: payload
}
},
TableName: 'TableName',
AttributesToGet: [
'attribute' // ...
],
ConsistentRead: false,
};
var sns_endpoint = null;
dynamodb.getItem(dynamodb_params, function(err, data) {
if (err) {
console.log(err.stack);
context.done(err, 'Errors while querying dynamodb!');
} else {
console.log(data);
sns_endpoint = data.Item.sns.S;
console.log("Result= " + data);
console.log("Item= " + data.Item);
console.log("sns= " + data.Item.sns);
console.log("value= " + data.Item.sns.S);
console.log("sns_endpoint= " + sns_endpoint);
context.done(null, 'Querying dynamodb succeeded!');
}
});
if( sns_endpoint != null ) {
console.log("sns_endpoint= " + sns_endpoint);
var sns_params = {
Message: payload,
Subject: 'Event Notification From Lambda',
TopicArn: sns_endpoint
};
var sns = new AWS.SNS();
sns.publish(sns_params, function(err, data) {
if (err) {
console.log(err.stack);
context.done(err, 'Errors while putting to SNS!');
} else {
console.log(data);
context.done(null, 'Putting to SNS succeeded!');
}
});
}
});
};
You are calling an asynchronous function, sns.publish(), within a forEach loop. Then you are immediately calling context.succeed(). As soon as context.succeed, context.fail or context.done are called, your Lambda function will exit. You need to modify your code to only call one of those after all asynchronous function calls have completed.
Related
Unable to get AWS Lambda to send message to an SQS Queue. I have removed the ids from the queue URL. The code doesn't fail but also doesn't send any message.
var AWS = require('aws-sdk');
exports.handler = async (event) => {
process.env['AWS_ACCESS_KEY_ID'] = process.env['AWS_ACCESS_KEY_ID_VAL'];
process.env['AWS_SECRET_ACCESS_KEY'] = process.env['AWS_SECRET_ACCESS_KEY_VAL'];
process.env['AWS_REGION'] = process.env['AWS_REGION_VAL'];
console.log("11")
AWS.config.update({region: 'ap-southeast-2'});
// Create an SQS service object
var sqs = new AWS.SQS({apiVersion: '2012-11-05'});
console.log("22")
var params = {
MessageBody: "This is a test message",
QueueUrl: "https://sqs.ap-southeast-2.amazonaws.com/11111111111/the-queue-name"
};
console.log("33")
var outcome = await sqs.sendMessage(params, await function(err, data) {
console.log("logging here")
if (err) {
console.log("Error", err);
} else {
//Log successful result id
console.log("Success", data.MessageId);
}
});
};
You will need promise() at the end of await sqs.sendMessage like this:
await sqs.sendMessage(
...
).promise();
Ref:
Example index.js file – AWS SDK with async handler and promises
https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html#nodejs-handler-async
I have a SNS mobile push notification service configured in AWS with FCM. I am able to send push notifications to a particular endpoint from the console with publish message.
But I want to publish a message to a particular endpoint from a Lambda function. I wrote a Lambda and gave necessary functions. But when I try to run the lambda there is no error thrown and no push notification actions.
Here is my code,
var AWS = require('aws-sdk');
var sns = new AWS.SNS();
exports.handler = async (event) => {
var params = {
TargetArn:'arn:aws:sns:eu-central-1:<my_user_id>:app/GCM/<my_sns_projectname>/<device-token>',
Message:'Success!!! ',
Subject: 'TestSNS'
};
await sns.publish(params , (err,data)=>{
if (err) {
console.log("Error sending a message " + err);
} else {
console.log("Sent message: " + data.MessageId);
}
})
};
I am a beginner, some help pls :)
Voila!! This worked for me!
var AWS = require('aws-sdk');
var sns = new AWS.SNS();
const params = {
TargetArn:'arn:aws:sns:eu-central-1:<my_user_id>:app/GCM/<my_sns_projectname>/<device-token>',
Message:JSON.stringify('Success!!! '),
Subject: 'TestSNS'
};
exports.handler = async (event, context, callback) => {
const publishPromise = sns.publish(params).promise();
await publishPromise.then((response) => {
console.log("SENT")
callback(null, "Message published.");
}, (err) => {
console.log("We had an error");
console.log(err);
callback("Message wasn’t able to publish.");
});
};
I have this lambda below that gets items from DynamoDB and returns it to connect just fine... however, I cannot seem to get the inputTranscript over. Is there a way I could implement this in my current lambda so that Connect can access it? I am seriously stumped on this, as everything I have tried in the documentation has not worked for me.
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
exports.handler = function(event, context, callback) {
console.log(`DEBUG:\t Event`, JSON.stringify(event, null, 4));
var params = {
Key: {
"name": {
"S": '"' + event.slots.list + '"'
}
},
TableName: 'ServiceOfferings'
};
dynamodb.getItem(params, function(err, data) {
if (err) {
console.log("ERROR:\t", err);
callback(err);
} else {
console.log(data);
if (data.Item) {
console.log('data returned from DynamoDB ', JSON.stringify(data));
callback(null, {
ServiceOffering: data.Item.name.S.slice(1, -1)
});
}
else {
console.log("no callback number found for intent");
callback(new Error("no callback number found for intent"));
}
}
});
};
The test instance I use to ensure the lambda works correctly is as follows:
{
"dialog-state": "ReadyForFulfillment",
"input-transcript": "my printer is not working",
"slots": {
"list": "Re-IP Project - Printers"
},
"intent-name": "getServiceOffering"
}
The response after Testing this comes out to:
{
"ServiceOffering": "Re-IP Project - Printers"
}
When you log the event, you should be able to see the inputTranscript being passed to your Lambda. So you simply need to take it out of the event and do with it what you want.
const AWS = require("aws-sdk");
const dynamodb = new AWS.DynamoDB();
exports.handler = function(event, context, callback) {
console.log(`DEBUG:\t Event`, JSON.stringify(event, null, 4));
var inputTranscript = event.inputTranscript
...
callback(null, {
ServiceOffering: data.Item.name.S.slice(1, -1),
inputTranscript: inputTranscript
});
That includes the inputTranscript in your callback to Connect (I assume), and you can use the Set Attribute block to save and handle the input within Connect.
I have an AWS Lambda function which is being triggered by AWS DynamoDB. The function checks if the operation in the DB is INSERT, and if it does, then it sends a new push message using AWS SNS:
console.log('Loading function');
var AWS = require('aws-sdk');
AWS.config.region = 'us-east-1';
exports.handler = function(event, context, callback) {
console.log("\n\nLoading handler\n\n");
var sns = new AWS.SNS();
console.log(JSON.stringify(event, null, 2));
event.Records.forEach(function(record) {
if (record.eventName == "INSERT") {
sns.publish({
Subject: 'Test',
Message: 'Test publish to SNS from Lambda',
TopicArn: 'TOPIC-ARN'
}, function(err, data) {
if (err) {
console.log(err.stack);
return;
}
console.log('push sent');
console.log(data);
context.done(null, 'Function Finished!');
});
}
});
callback(null, "message");
};
Is there a way that I could get the attributes of the newly added item?
var id = record.dynamodb.Keys.Id.N;
I have a problem with my lambda function. It takes the data of the devices and sends the push notification (information that someone added you to friends). However, it often happens that the push notificaiton is not sent. Sometimes, I have to activate the function couple of times (through simultaneous clicking on the button) to make it send push notifications. When testing the below function in Lambda it does not send any push notifications. What might be the issue?
Thank you in advance,
John
console.log("Loading friend-request function");
var AWS = require("aws-sdk");
exports.handler = function(event, context) {
var senderID = event.senderID;
var receiverID = event.receiverID;
var message = event.message;
var eventText = JSON.stringify(event);
console.log("Received event:", eventText);
var sns = new AWS.SNS();
var params = {
Message: message,
Subject: "Test SNS From Lambda",
TargetArn: receiverID
};
context.succeed(message);
sns.publish(params, context.done);
};
Remember that the sns.publish() function is asynchronous, i.e. you must wait for it to complete before you can call the context.succeed(). Otherwise, the Lambda function may terminate before the message has been published.
exports.handler = function(event, context) {
// same as before...
var params = {...}
// do not call context.succeed() yet
sns.publish(params, function(err, data) {
if (err) {
console.log('Failed to publish SNS message');
context.fail(err);
}
else {
console.log('SNS message published successfully');
context.succeed(data);
}
});
};