Home > Blockchain >  Lambda function handler executing DynamoDB update twice
Lambda function handler executing DynamoDB update twice

Time:11-11

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);
  }
);

CodePudding user response:

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();

CodePudding user response:

Are you using DynamoDB Streams to trigger this Lambda also?

Easiest way to overcome this is by logging the event object at the beginning of the handler, inside the logs in CloudWatch you will be able to see where the Lambda was triggered from.

This will allow you to understand what is happening and avoid speculation.

  • Related