b_a9f
b_a9f

Reputation: 7

Lambda function handler executing DynamoDB update twice

My Lambda function is supposed to increment a value in a dynamodb table, I'm using the .update API as an atomic counter. The value is incremented twice! I tried to change the increment variable value and it always increments twice. For example: the value in my DynamoDB table is 2, and the increment value is 1. I test the Lambda function, and the dynamoDB value is 4 (instead of 3).

The same code (without the handler function) works successfully from outside Lambda (executed from VSCode using the JS SDK) What could be the issue?

'use strict';

const AWS = require("aws-sdk");
AWS.config.update({ region: "me-central-1" });

const docClient = new AWS.DynamoDB.DocumentClient();

exports.handler = async (event) => {
await docClient.update(
  {
    TableName: "visitor-counter-table",
    Key: {
      "visitor-counter": "counter",
    },
    UpdateExpression: "set #num = #num + :incr",
    ExpressionAttributeNames: {
      "#num": "number",
    },
    ExpressionAttributeValues: {
      ":incr": 1,
    },
  },
  (err, data) => {
    err ? console.log(err) : console.log(data);
  }
).promise();

  return {"statusCode": 200, "body": "number added to DDB Success"}
};

Here is the code i ran on VSCode:

const AWS = require("aws-sdk");
AWS.config.update({ region: "me-central-1" });

const docClient = new AWS.DynamoDB.DocumentClient();

docClient.update(
  {
    TableName: "visitor-counter-tbl",
    Key: {
      "visitor-counter": "counter",
    },
    UpdateExpression: "set #num = #num + :incr",
    ExpressionAttributeNames: {
      "#num": "number",
    },
    ExpressionAttributeValues: {
      ":incr": 1,
    },
  },
  (err, data) => {
    err ? console.log(err) : console.log(data);
  }
);

Upvotes: 0

Views: 240

Answers (1)

Ermiya Eskandary
Ermiya Eskandary

Reputation: 23692

You're passing success and failure callbacks to docClient.update while also obtaining and awaiting a generated promise.

This means that ultimately you're triggering the update twice.

The reason why your local invocation works is that you're only passing the callbacks, and not asking for a promise (.promise()) and then awaiting it. This results in triggering the update once.

Either use await, or use callbacks - not both.

This should work:

await docClient.update(
  {
    TableName: "visitor-counter-table",
    Key: {
      "visitor-counter": "counter",
    },
    UpdateExpression: "set #num = #num + :incr",
    ExpressionAttributeNames: {
      "#num": "number",
    },
    ExpressionAttributeValues: {
      ":incr": 1,
    },
  }
).promise();

Upvotes: 1

Related Questions