使用 Lambda 查询 DynamoDB 没有任何作用
我有以下 Lambda 函数代码:
console.log('加载函数');var aws = require('aws-sdk');var ddb = 新 aws.DynamoDB();函数获取用户(用户 ID){var q = ddb.getItem({表名:用户",钥匙: {用户 ID:{ S:用户 ID } }},函数(错误,数据){如果(错误){控制台日志(错误);返回错误;}别的 {控制台.log(数据);}});控制台.log(q);}export.handler = 函数(事件,上下文){console.log('收到事件');获取用户('user1');console.log("称为 DynamoDB");context.succeed();};
我有一个这样定义的 [Users] 表:
<代码>{"cognitoID": { "S": "token" },电子邮件":{S":user1@domain.com"},密码":{S":密码"},"tos_aggreement": { "BOOL": true },用户ID":{S":用户1"}}
当我(从 AWS 控制台或 CLI)调用函数时,我可以在日志中看到消息,但从未调用 getItem() 的回调.
我尝试在没有回调的情况下执行 getItem(params),然后定义了完成、成功和失败的回调,但是当我执行 send() 时,甚至也不调用完整的回调.
我知道调用是异步的,我想也许 lambda 函数在查询完成之前就完成了,因此不会调用回调,但是,我在函数末尾添加了一个简单的愚蠢循环,并且调用在 3 秒后超时,根本没有调用回调.
我尝试了不同的函数 batchGetItem、getItem、listTables 和扫描.结果是一样的,没有错误,但是回调函数永远不会被调用.
我敢打赌,如果我在不使用 Lambda 的情况下查询 dynamoDB,它会得到结果,所以我真的很想知道为什么这里什么都没有发生.
我为该函数创建了一个角色,并创建了一个策略,允许访问 dynamoDB 中我需要但无济于事的功能.
政策如下所示:
<块引用><代码>{版本":2012-10-17",陈述": [{效果":允许",行动": [lambda:InvokeFunction"],资源":arn:aws:lambda:*:*:*"},{效果":允许",行动": ["dynamodb:GetItem","dynamodb:BatchGetItem",dynamodb:扫描","dynamodb:PutItem",dynamodb:查询","dynamodb:GetRecords",dynamodb:列表表"],资源":arn:aws:dynamodb:*:*:*"},{行动": [日志:*"],效果":允许",资源":*"}]}
我在模拟器中运行了该策略,它按我想的那样工作.有什么建议吗?
解决方案所以,结果证明代码是正确的.问题是 dynamodb API 使用了所有这些回调,并且基本上函数在数据被检索之前结束.
最快的解决方法是删除 context.succeed()
调用,然后将检索数据.当然,使用 async 模块会有所帮助,如果您不想使用它,只需在回调中添加一个计数器或布尔值,然后等到值发生变化,表明回调已被调用(哪种很烂如果你想的话)
I have the following code for a Lambda function:
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();
};
I have a [Users] table that is defined as such:
{
"cognitoID": { "S": "token" },
"email": { "S": "user1@domain.com" },
"password": { "S": "somepassword" },
"tos_aggreement": { "BOOL": true },
"userID": { "S": "user1" }
}
When I call the function (from the AWS Console or the CLI) I can see the messages in the logs but the callback for the getItem() is never called.
I tried with doing getItem(params) with no callback, then defined the callbacks for complete, success and failure but when I do the send(), even the complete callback isn't called either.
I know that the calls are asynchronous and I thought that maybe, the lambda function was finishing before the query was done and therefore the callback would not be called, but, I added a simple stupid loop at the end of the function and the call timed out after 3 seconds, without the callbacks being called at all.
I tried with different functions batchGetItem, getItem, listTables and scan. Result is the same, no error but the callback function is never called.
I'm betting that if I query dynamoDB without using Lambda it will get me the results so I'm really wondering why nothing is happening here.
I create a role for the function and I created a policy that would allow access to the functionalities in dynamoDB that I need but to no avail.
The policy looks like this:
{ "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": "*" } ] }
I ran the policy in the simulator and it worked as I thought it would. Suggestions?
解决方案So, it turns out that the code is correct. The problem is that the dynamodb API uses all those callbacks and basically the function ends BEFORE the data has been retrieved.
The quickest fix is to remove the context.succeed()
call and the data will be retrieved.
Of course using the async module would help and if you don't want to use that, just add a counter or a boolean to your callback and then wait until the value has changed, indicating that the callback has been called (which kind of sucks if you think of it)
相关文章