Reputation: 13
I'm trying to push a record from the AWS Lambda function to the AWS DynamoDB. I can successfully push a record from my pc using AWS API but when I deploy the code to AWS I'm stuck.
Here's the example code that can successfully push a record from my PC:
const AWS = require("aws-sdk");
AWS.config.update({
region: "eu-west-1",
endpoint: "https://dynamodb.eu-west-1.amazonaws.com"
});
const docClient = new AWS.DynamoDB.DocumentClient();
const params = {
TableName: "hello-world-bot",
Item: {
timestamp: Date.now(),
chat_id: 123,
text: 'text',
},
};
console.log("Adding a new item...");
docClient.put(params, function(err, data) {
if (err) {
console.error("Unable to add item. Error JSON:", JSON.stringify(err, null, 2));
} else {
console.log("Added item:", JSON.stringify(data, null, 2));
}
});
And the result in DynamoDB: Screenshot from DynamoDB console
And here's the code I'm trying to deploy to Lambda:
const AWS = require("aws-sdk");
AWS.config.update({
region: "eu-west-1",
endpoint: "https://dynamodb.eu-west-1.amazonaws.com",
});
const docClient = new AWS.DynamoDB.DocumentClient();
module.exports.helloworld = (event) => {
const params = {
TableName: "hello-world-bot",
Item: {
timestamp: Date.now(),
chat_id: 123,
text: "text",
},
};
console.log("Adding a new item...");
docClient.put(params, function (err, data) {
if (err) {
console.error(
"Unable to add item. Error JSON:",
JSON.stringify(err, null, 2)
);
} else {
console.log("Added item:", JSON.stringify(data, null, 2));
}
});
return { statusCode: 200 };
};
And the trouble is that there are no any records in DynamoDB when Lambda function runs. Here are logs from CloudWatch when I pull Lambda external API and try to run the function:
START RequestId: d9e171c2-a763-4df1-9ec3-06d79eb68a1e Version: $LATEST
2021-08-13T06:03:01.974Z d9e171c2-a763-4df1-9ec3-06d79eb68a1e INFO Adding a new item...
END RequestId: d9e171c2-a763-4df1-9ec3-06d79eb68a1e
REPORT RequestId: d9e171c2-a763-4df1-9ec3-06d79eb68a1e Duration: 45.04 ms Billed Duration: 46 ms Memory Size: 1024 MB Max Memory Used: 88 MB Init Duration: 524.54 ms
As you can see there are no any errors saying anything about permissions or else. These are the user permissions whose credentials are used with this function in Lambda:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:BatchGetItem",
"dynamodb:GetItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:BatchWriteItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem"
],
"Resource": "arn:aws:dynamodb:eu-west-1:120400915578:table/hello-world-bot"
}
]
}
Upvotes: 1
Views: 1867
Reputation: 4070
your return { statusCode: 200 };
ends the lambda invocation, but it does not wait for the put
request to finish. It probably don't even wait for it to start, actually.
Either return your main function from the put
callback, or use promises. Example with promise:
module.exports.helloworld = async (event) => { // <- use async
const params = {
TableName: "hello-world-bot",
Item: {
timestamp: Date.now(),
chat_id: 123,
text: "text",
},
}
console.log("Adding a new item...")
// Create a promise and return it
return docClient
.put(params)
.promise()
.then(() => {
console.log("success")
return {statusCode: 200}
})
.catch(e => {
console.log("error: ", e)
return {statusCode: 500}
})
}
Also, as pointed out by @jens in the comments, explicitely setting a dynamodb endpoint is not required
Upvotes: 0
Reputation: 3564
As I've pointed out in the comments of the other answer, their return statements do not seem entirely correct. I would prefer to use async-await syntax for promises which are supported by lambda and the AWS SDK out of the box.
This would change your code to look like the following:
const AWS = require("aws-sdk");
const docClient = new AWS.DynamoDB.DocumentClient();
module.exports.helloworld = async (event) => {
const params = {
TableName: "hello-world-bot",
Item: {
timestamp: Date.now(),
chat_id: 123,
text: "text",
},
};
console.log("Adding a new item...");
try {
await docClient.put(params).promise();
return { statusCode: 200 };
} catch (err) {
console.error("Unable to add item. Error JSON:",
JSON.stringify(err, null, 2));
return { statusCode: 500 };
}
};
PS: As pointed out in the comments as well, you don't need to set the endpoint for DynamoDB if you're using the default endpoint. And since you're running the function as a Lambda an AWS_REGION
environment variable will be set automatically, so you also don't need to configure this yourself (unless you want to access a DynamoDB table in another region).
Upvotes: 1