0

I'm working with some business code that handles a given event, queries a MySQL DB and then uploads a formatted object to DynamoDB. The code looks like this:

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

var pool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_DATABASE
});

module.exports.handle = (event, context, callback) => {
  context.callbackWaitsForEmptyEventLoop = false;
  console.time("query");

  // more code

  pool.getConnection(function (err, connection) {
    if (err) callback(Error(`could not get a pool connection: ${err}`));

    connection.query(query, (err, res, fields) => {
      connection.release();
      if (err) {
        callback(Error(`could not execute query: ${err}`));
      } else {
        console.timeEnd("query");
        console.time("parsing");

        // more code

        let inputItem = {
          Item: item,
          TableName: "some_table"
        }

        console.timeEnd("parsing");
        console.time("putItem");

        // here it hangs... no err, no data

        dynamodb.putItem(inputItem, function (err, data) {
          if (err) callback(Error(`could not putItem: ${err}`))
          console.timeEnd("putItem");
          callback(null, JSON.stringify({
            message: "OK"
          }));
        });

      }
    });
  });
}

I used Serverless to bundle this code and deployed it to AWS. When I execute the lambda locally using sls invoke local it works, but when I try to run the deployed one (either from sls or the AWS console) I get a timeout every time.

It's REALLY strange, because if I delete the MySQL code it works, i.e. it puts the item to DynamoDB. In fact the original code was a Go lambda. With that code I had exactly the same error, when calling one AWS service: no problem, when calling MySQL and then a AWS service, hangs... Tried all different version of Go, AWS-SDK packages, etc... Decided to migrate it to Node, thinking it's a Go problem. I don't really know what's going on...

In terms of roles and permissions, they are OK, as I said, the code WORK if I only call a AWS service during the Lambda execution.

Any ideas on what could be wrong, or if I'm just an idiot missing something?

I guess the unique solution will be to chain Lambdas...

2pac
  • 73
  • 2
  • 6
  • Where is your MySQL server running? Is it RDS? Ultimately it sounds like there is a firewall type of issue preventing Lambda from connecting to MySQL. – stdunbar May 05 '20 at 20:26
  • No, I don´t have problems connecting to the SQL. The DB is in RDS inside a VPC. The lambda has it´s sec group and all, so it can connect to it. – 2pac May 05 '20 at 20:32
  • What does it mean "call a AWS service during the Lambda execution"? How you can call it outside of Lambda execution? – Marcin May 05 '20 at 21:57
  • I mean just calling DynamoDB, or Eventbridge, for example. – 2pac May 05 '20 at 22:02

1 Answers1

0

I made some research and found out that this is realed on how the VPC is configured. I turns out that the Lambda does not have access to the internet from within the VPC, so you need to either:

  1. Configure a DB Proxy (not recommended for production as it's in beta preview) and make the connection to the DB via this.
  2. Configure the VPC to have access to the internet.

Sources:

2pac
  • 73
  • 2
  • 6