Lambda中的DynamoDB updateItem静默失败

时间:2019-05-07 11:42:46

标签: amazon-web-services aws-lambda amazon-dynamodb

我正在尝试使用Lambda函数实现一个简单的计数器,但是每当我对其进行测试时,下面的updateItem都不起作用:回调中的所有log语句都不会运行,当然还有相关的计数器在表中永远不会更新。这是我的lambda函数:

'use strict';
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB({ apiVersion: '2012-08-10' });

let params = {
    TableName: 'Counters',
    Key: {
        'name': { S: 'global' }
    },
    UpdateExpression: 'SET val = val + :inc',
    ExpressionAttributeValues: {
        ':inc': { N: '1' }
    },
    ReturnValues: 'ALL_NEW'
};

exports.handler = async(event) => {
    console.log("Invoked counter-test");

    dynamodb.updateItem(params, function(err, data) {
        console.log("In updateItem callback");
        if (err)
            console.log(err, err.stack);
        else
            console.log(data);
    });

    console.log("Updated counter");

    const response = {
        statusCode: 200,
        body: JSON.stringify('Counter updated'),
    };
    return response;
};

这是测试的输出:

Response:
{
  "statusCode": 200,
  "body": "\"Counter updated\""
}

Request ID:
"80e92299-2eea-45e4-9c68-54ccf87199c5"

Function Logs:
START RequestId: 80e92299-2eea-45e4-9c68-54ccf87199c5 Version: $LATEST
2019-05-07T11:34:21.931Z    80e92299-2eea-45e4-9c68-54ccf87199c5    Invoked counter-test
2019-05-07T11:34:21.934Z    80e92299-2eea-45e4-9c68-54ccf87199c5    Updated counter
END RequestId: 80e92299-2eea-45e4-9c68-54ccf87199c5
REPORT RequestId: 80e92299-2eea-45e4-9c68-54ccf87199c5  Duration: 275.91 ms Billed Duration: 300 ms     Memory Size: 128 MB Max Memory Used: 67 MB  

如您所见,没有运行来自updateItems回调的日志语句。

如果我尝试使用aws dynamodb从命令行更新计数器,则它确实可以工作,但是:

$ aws dynamodb update-item \
  --table-name Counters \
  --key '{"name": { "S": "global" }}' \
  --update-expression 'SET val = val + :inc' \
  --expression-attribute-values '{":inc": {"N": "1"}}' \
  --return-values ALL_NEW \
  --output json
{
    "Attributes": {
        "name": {
            "S": "global"
        },
        "val": {
            "N": "129"
        }
    }
}

1 个答案:

答案 0 :(得分:4)

这是由于Java语言的异步特性。

方法updateItem是异步的,您不必等待回调被触发再返回(您开始updateItem操作,然后立即返回响应)。

如果要维护回调模式,则应执行以下操作:

exports.handler = (event, context, callback) => {
    console.log("Invoked counter-test");

    dynamodb.updateItem(params, function(err, data) {
        console.log("In updateItem callback");
        if (err) {
            console.log(err, err.stack);
            callback(err);
        } else {
            console.log(data);
            console.log("Updated counter");
            const response = {
                statusCode: 200,
                body: JSON.stringify('Counter updated'),
            };
            callback(null, response);
        }
    });
};

使用承诺:

exports.handler = (event, context, callback) => {
    console.log("Invoked counter-test");

    dynamodb.updateItem(params).promise()
        .then((data) => {
            console.log(data);
            console.log("Updated counter");

            const response = {
                statusCode: 200,
                body: JSON.stringify('Counter updated'),
            };
            callback(null, response);          
        });
        .catch((err) => {
          console.log(err, err.stack);
          callback(err);
        })
};

使用await(推荐):

exports.handler = async (event) => {
    try {
        console.log("Invoked counter-test");

        const data = await dynamodb.updateItem(params).promise();
        console.log(data);

        console.log("Updated counter");

        const response = {
            statusCode: 200,
            body: JSON.stringify('Counter updated'),
        };
        return response;      
    } catch (err) {
      console.log(err, err.stack);
      throw err;
    }
};

另请参见Understanding Asynchronous JavaScriptDeeply Understanding JavaScript Async and Await with ExamplesAWS SDK for Javascript - Using JavaScript Promises