使用 Lambda 查询 DynamoDB 什么都不做
Querying DynamoDB with Lambda does nothing
我有以下 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] table 是这样定义的:
{
"cognitoID": { "S": "token" },
"email": { "S": "user1@domain.com" },
"password": { "S": "somepassword" },
"tos_aggreement": { "BOOL": true },
"userID": { "S": "user1" }
}
当我调用该函数(从 AWS 控制台或 CLI)时,我可以在日志中看到消息,但从未调用 getItem() 的回调。
我尝试在没有回调的情况下执行 getItem(params),然后定义完成、成功和失败的回调,但是当我执行 send() 时,即使是完整的回调也没有被调用。
我知道调用是异步的,我想也许 lambda 函数在查询完成之前完成,因此不会调用回调,但是,我在函数的末尾添加了一个简单的愚蠢循环函数和调用在 3 秒后超时,根本没有调用回调。
我尝试了不同的函数 batchGetItem、getItem、listTables 和 scan。结果是一样的,没有错误但是回调函数没有被调用。
我敢打赌,如果我在不使用 Lambda 的情况下查询 dynamoDB,它会得到结果,所以我真的很想知道为什么这里什么也没有发生。
我为函数创建了一个角色,并创建了一个策略,允许访问我需要的 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": "*"
}
]
}
我 运行 模拟器中的策略,它按照我的预期工作。
建议?
所以,事实证明代码是正确的。
问题是 dynamodb API 使用了所有这些回调,基本上函数在检索到数据之前就结束了。
最快的解决方法是删除 context.succeed()
调用,然后将检索数据。
当然使用异步模块会有所帮助,如果你不想使用它,只需在你的回调中添加一个计数器或一个布尔值,然后等到值发生变化,表明回调已被调用(这很糟糕如果你想到了)
我遇到了一些类似的问题,但没有找到很多有用的资源。这就是我最终要做的。可能更聪明的人可以告诉我们这是否是最好的。
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);
});
总而言之,通过主函数将回调传递给较小的函数,允许应用程序继续执行直到完成 Dynamo。保留辅助功能中的 context.succeed 或在那里继续其他功能。
要避免回调地狱,请使用 Promises。 youtube 上有一些很好的教程,作者是 funfunfunction。
我的问题是我的 lambda 运行 在 VPC 中以便连接到 ElastiCache。这会导致对 public Internet 资源(例如 DynamoDB 和 API 网关)的任何查询无限期挂起。我必须在我的 VPC 中设置 NAT 网关才能访问 DynamoDB。
现在由于 node.js 引入了 async/await,这可以让它在主函数终止之前等待查询调用 returns:
let result = await ddb.getItem(params).promise();
return result;
我的问题是我尝试调用的函数接受了回调。
Node.js 因此只是继续执行 Lambda 函数,一旦执行结束,它 告诉 Lambda 关闭,因为它已完成.
这是一个如何使用 Promises 解决问题的示例:
'use strict';
exports.handler = async (event, context) => {
// WRAP THE FUNCTION WHICH USES A CALLBACK IN A PROMISE AND RESOLVE IT, WHEN
// THE CALLBACK FINISHES
return await new Promise( (resolve, reject) => {
// FUNCTION THAT USES A CALLBACK
functionThatUsesACallback(params, (error, data) => {
if(error) reject(error)
if(data) resolve(data)
});
});
};
我有以下 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] table 是这样定义的:
{
"cognitoID": { "S": "token" },
"email": { "S": "user1@domain.com" },
"password": { "S": "somepassword" },
"tos_aggreement": { "BOOL": true },
"userID": { "S": "user1" }
}
当我调用该函数(从 AWS 控制台或 CLI)时,我可以在日志中看到消息,但从未调用 getItem() 的回调。
我尝试在没有回调的情况下执行 getItem(params),然后定义完成、成功和失败的回调,但是当我执行 send() 时,即使是完整的回调也没有被调用。
我知道调用是异步的,我想也许 lambda 函数在查询完成之前完成,因此不会调用回调,但是,我在函数的末尾添加了一个简单的愚蠢循环函数和调用在 3 秒后超时,根本没有调用回调。
我尝试了不同的函数 batchGetItem、getItem、listTables 和 scan。结果是一样的,没有错误但是回调函数没有被调用。
我敢打赌,如果我在不使用 Lambda 的情况下查询 dynamoDB,它会得到结果,所以我真的很想知道为什么这里什么也没有发生。
我为函数创建了一个角色,并创建了一个策略,允许访问我需要的 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": "*" } ] }
我 运行 模拟器中的策略,它按照我的预期工作。 建议?
所以,事实证明代码是正确的。 问题是 dynamodb API 使用了所有这些回调,基本上函数在检索到数据之前就结束了。
最快的解决方法是删除 context.succeed()
调用,然后将检索数据。
当然使用异步模块会有所帮助,如果你不想使用它,只需在你的回调中添加一个计数器或一个布尔值,然后等到值发生变化,表明回调已被调用(这很糟糕如果你想到了)
我遇到了一些类似的问题,但没有找到很多有用的资源。这就是我最终要做的。可能更聪明的人可以告诉我们这是否是最好的。
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);
});
总而言之,通过主函数将回调传递给较小的函数,允许应用程序继续执行直到完成 Dynamo。保留辅助功能中的 context.succeed 或在那里继续其他功能。
要避免回调地狱,请使用 Promises。 youtube 上有一些很好的教程,作者是 funfunfunction。
我的问题是我的 lambda 运行 在 VPC 中以便连接到 ElastiCache。这会导致对 public Internet 资源(例如 DynamoDB 和 API 网关)的任何查询无限期挂起。我必须在我的 VPC 中设置 NAT 网关才能访问 DynamoDB。
现在由于 node.js 引入了 async/await,这可以让它在主函数终止之前等待查询调用 returns:
let result = await ddb.getItem(params).promise();
return result;
我的问题是我尝试调用的函数接受了回调。
Node.js 因此只是继续执行 Lambda 函数,一旦执行结束,它 告诉 Lambda 关闭,因为它已完成.
这是一个如何使用 Promises 解决问题的示例:
'use strict';
exports.handler = async (event, context) => {
// WRAP THE FUNCTION WHICH USES A CALLBACK IN A PROMISE AND RESOLVE IT, WHEN
// THE CALLBACK FINISHES
return await new Promise( (resolve, reject) => {
// FUNCTION THAT USES A CALLBACK
functionThatUsesACallback(params, (error, data) => {
if(error) reject(error)
if(data) resolve(data)
});
});
};