Запрос DynamoDB с Lambda ничего не делает
У меня есть следующий код для функции лямбда:
console.log('Loading function');
var aws = require('aws-sdk');
var ddb = new aws.DynamoDB();
function getUser(userid) {
var q = ddb.getItem({
TableName: "Users",
Key: {
userID: { S: userid } }
}, function(err, data) {
if (err) {
console.log(err);
return err;
}
else {
console.log(data);
}
});
console.log(q);
}
exports.handler = function(event, context) {
console.log('Received event');
getUser('user1');
console.log("called DynamoDB");
context.succeed();
};
У меня есть таблица [Users], которая определяется как таковая:
{
"cognitoID": { "S": "token" },
"email": { "S": "[email protected]" },
"password": { "S": "somepassword" },
"tos_aggreement": { "BOOL": true },
"userID": { "S": "user1" }
}
Когда я вызываю функцию (из консоли AWS или CLI), я могу видеть сообщения в журналах, но обратный вызов для getItem() никогда не вызывается.
Я попытался с выполнением getItem (params) без обратного вызова, а затем определил обратные вызовы для полного, успешного и неудачного, но когда я делаю send(), даже полный обратный вызов также не вызывается.
Я знаю, что вызовы асинхронны, и я подумал, что, возможно, лямбда-функция заканчивалась до того, как запрос был выполнен, и поэтому обратный вызов не будет вызываться, но я добавил простой глупый цикл в конце функции и вызов завершается через 3 секунды без вызова обратных вызовов.
Я пробовал с различными функциями batchGetItem, getItem, listTables и scan. Результат одинаков, нет ошибки, но функция обратного вызова никогда не вызывается.
Я уверен, что если я запрошу dynamoDB без использования Lambda, это даст мне результаты, поэтому мне действительно интересно, почему здесь ничего не происходит.
Я создаю роль для этой функции, и я создал политику, которая позволила бы получить доступ к функциям в dynamoDB, которые мне нужны, но безрезультатно.
Политика выглядит так:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:InvokeFunction"
],
"Resource": "arn:aws:lambda:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:BatchGetItem",
"dynamodb:Scan",
"dynamodb:PutItem",
"dynamodb:Query",
"dynamodb:GetRecords",
"dynamodb:ListTables"
],
"Resource": "arn:aws:dynamodb:*:*:*"
},
{
"Action": [
"logs:*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
Я запустил политику в симуляторе, и это сработало, как я думал.
Предложения?
Ответы
Ответ 1
Итак, оказывается, что код правильный.
Проблема заключается в том, что API-интерфейс dynamodb использует все эти обратные вызовы и в основном функция заканчивается до того, как данные были восстановлены.
Самое быстрое исправление - удалить вызов context.succeed()
, и данные будут восстановлены.
Конечно, использование асинхронного модуля помогло бы, и если вы не захотите это использовать, просто добавьте счетчик или логическое значение в ваш обратный вызов, а затем подождите, пока значение не изменится, что указывает на то, что вызван обратный вызов (какой отстой если вы думаете об этом)
Ответ 2
У меня были некоторые подобные проблемы, и я не нашел много полезных ресурсов. Вот что я в итоге сделал. Возможно, кто-то умнее скажет нам, если это самое лучшее.
function getHighScores(callback) {
var params = {
TableName : 'sessions',
ScanFilter: {"score":{"AttributeValueList":[{"N":"0"}], "ComparisonOperator":"GT"}},
};
var dynamo = new AWS.DynamoDB();
dynamo.scan(params, function(err, data) {
if (err) {
console.log (err)
callback(err);
} else {
callback(data.Items);
console.log(data.Items);
}
});
}
getHighScores(function (data) {
console.log(data);
context.succeed(data);
});
Таким образом, передача обратного вызова через основную функцию в меньшую функцию позволяет приложению продолжать работу до завершения Динамо. Сохраняйте context.success в вторичной функции или продолжать другие функции там.
Ответ 3
Моя проблема в том, что моя лямбда работала в VPC, чтобы подключиться к ElastiCache. Это вызывает любые запросы к общедоступным интернет-ресурсам, таким как DynamoDB и Gateway API, чтобы вешать бесконечно. Я должен был настроить NAT-шлюз в своем VPC для доступа к DynamoDB.
Ответ 4
Чтобы избежать аддонов обратного вызова, используйте Promises. На youtube есть несколько хороших обучающих программ, которые называют funfunfunction.