0
votes

I am attempting to delete a record from DynamoDB using Lambda and API gateway. Currently the Id of the record is passed as a query parameter, which is passed to my deleteRecord lambda function, and used in the delete function of the documentClient.

Currently, I receive errors when trying to delete a record, yet the record is deleted anyway, and I can't figure out why.

When testing on the API gateway, I receive "Internal server error" as a response, yet inspection of the table shows that the item is deleted, and the logs show me the record that has been deleted (as per supplying ReturnValues: "ALL_OLD" in the params passed to documentClient).

When testing on Lambda directly (manually inserting the ID into my dt.delete function), I get the following:

Response:
{
  "errorMessage": "RequestId: xxxxxxxxxxxxxxxxxxxx Process exited before completing request"
}

Request ID:
"xxxxxxxxxxxxxxxxxxxx"

Function Logs:
START RequestId: xxxxxxxxxxxxxxxxxxxx Version: $LATEST
2019-04-04T10:21:55.637Z    xxxxxxxxxxxxxxxxxxxx    Promise { <pending> }
2019-04-04T10:21:55.938Z    xxxxxxxxxxxxxxxxxxxx    TypeError: undefined is not a function
    at Response.<anonymous> (/var/task/deleteTrip.js:28:28)
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:364:18)
    at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)
END RequestId: xxxxxxxxxxxxxxxxxxxx
REPORT RequestId: xxxxxxxxxxxxxxxxxxxx  Duration: 941.48 ms Billed Duration: 1000 ms    Memory Size: 128 MB Max Memory Used: 67 MB  
RequestId: xxxxxxxxxxxxxxxxxxxx Process exited before completing request

Despite the error, the record is deleted from the table in this instance as well.

I have followed the DocumentClient documentation for deleting a record, however it does not explain how to pass back a response (instead just logs the data from the call back), so I am not sure if this is my problem.

Lambda Functions
Index.js:

const deleteTrip = require('./deleteTrip.js');
const dt = new deleteTrip();

exports.handler = async (event) => {
    return dt.delete(event.queryStringParameters['Id']);
};

deleteTrip.js:

const AWS = require('aws-sdk');

let documentClient = new AWS.DynamoDB.DocumentClient({
    'region': 'eu-west-1'
});

module.exports = class deleteTrip {
    delete(Id) {
        return new Promise((resolve, reject) => {
            if (typeof Id !== 'string') throw `Expected: "String", received: ${typeof Id}`;
            let params = {
                TableName: "xyzDataTable",
                Key: {
                    tripId: Id
                },
                ReturnValues: "ALL_OLD",
                Exists: true
            };
            documentClient.delete(params, function(err, data) {
                if (err) {
                    console.log("Error deleting record from dynamoDB:", err);
                    console.log(params);
                    return reject(err);
                } else {
                    return resolve(...data.Attributes);
                }
            })
        });

    }
}

I expect the details of the deleted item to be returned if the request was successful, and an error to be thrown if not.

2
All SDK functions have a .promise() method that you can use instead of using callbacks and manufacturing your own promises. For example: rsp = await documentClient.delete(...).promise()jarmod
Would this be within the new Promise or instead of? When I try this immediately within the delete function, I get Parsing error: unexpected token documentClient when used with await.aidan_7

2 Answers

0
votes

Here's an example of how to use promises with the DynamoDB DocumentClient (or, in fact the lower-level DynamoDB APIs as well):

const AWS = require('aws-sdk');

let documentClient = new AWS.DynamoDB.DocumentClient({
    'region': 'eu-west-1'
});

class deleteTrip {
    delete(Id) {
        const params = {
            TableName: "xyzDataTable",
            Key: {
                tripId: Id
            },
            ReturnValues: "ALL_OLD",
            Exists: true
        };
        return documentClient.delete(params).promise();
    }
}

const testing = async (id) => {
    try {
        const dt = new deleteTrip();
        const data = await dt.delete(id);
        console.log("Success:", data);

    } catch(err) {
        console.log("Error:", err);
    }
}

testing(101);

Also note that a delete operation will be successful, i.e. will not report any error, if you attempt to delete a non-existent item. That's treated as successful and is just the nature of DynamoDB.

0
votes

In Lambda, the function will exit as soon as the exported handler returns a value. You are returning a promise and the process is exiting before it even resolves.

Make the following changes in index.js

const deleteTrip = require('./deleteTrip.js');
const dt = new deleteTrip();

exports.handler = async (event) => {
    try{
        var result = await dt.delete(event.queryStringParameters['Id']);
        return res;
    }
    catch(err){
        //if the delete function throws an error or the promise rejects
        return err;
    }
};