Connecting to MySql database from AWS Lambda function using Node.js, no connect callback

I am trying to connect an external (not AWS) MySql server from an AWS Lambda function written in Node.js using nodejs14.x environment, but the connect() callback is not called.

I am been struggling with this problem since days, there are a lot of references to similar issues but I really tried all possible permutations of solutions I found.

I am deploying with SAM and testing both on local machine and on real AWS.

Here is the sample code of the lambda helper

    const mysql = require('mysql');

    exports.helloFromLambdaHandler = async () => {

    const message = 'Hello from Lambda!';

    console.info(`${message}`);
    
    var sql = "SELECT 1+? AS sum";
    var values = [1];

    console.log("Doing createConnection");
    const connection = mysql.createConnection({
        /* my connection data */
      });
    
    console.log("Doing connect");
    connection.connect( (err) => {
        console.log("Inside connection callback");
        console.log('connected as id ' + connection.threadId);

        if(!err) {
          console.log("DB connected, thread id is "  + connection.threadId);
          console.log("Doing query");

          connection.query(sql, values, (err, result, values) => {
            console.log("Inside query callback");
            if(!err) {
              console.log("Query ok!");
              console.log(result);
              connection.end();
            } else {
              console.log("Error executing query: " + err.message);
            }       
          });
          
        } else {
          console.log("Error connecting db: "+ err.message);
        }
      });

    console.log ("Returning...");
    return message;
}

The log is

Hello from Lambda!
Doing createConnection
Doing connect
Returning...

The expected behaviour is that after “Returning…” I should see the log “Inside connection callback” then “Inside query callback” and then “Query ok!”.

Instead the callback of connect() appears not invoked.

I know that I can call query() directly skipping connect() but also doing so I encounter same issue.

Any clue?

Thank you!

SOLUTION

As suggested by the accepted answer, returning a promise is the solution to let Node complete all the queue. Unfortunately it’s not possible to complete the Lambda and leave it running in background in a safe manner, for what I understand.

I am investigating alternative solutions such as:

  • mysql2 library which supports promises natively
  • serverless-mysql npm package which handles shared db connections

Below the running demo code

const mysql = require('mysql');

exports.helloFromLambdaHandler = async (event, context) => {

    const message = 'Hello from Lambda!';

    console.info(`${message}`);
    
    var sql = "SELECT 1+? AS sum";
    var values = [1];

    console.log("Doing createConnection");
    const connection = mysql.createConnection({
        /* my connection data */
      });
    
    console.log("Doing query");

    const promise = new Promise( (resolve, reject) => {
        connection.query(sql, values, (err, result, values) => {
        console.log("Inside query callback");
        if(!err) {
            console.log("Query ok!");
            console.log(result);
            connection.end();
            resolve(message);
        } else {
            console.log("Error executing query: " + err.message);
            reject(err);
        }       
        });
    });

    console.log ("Returning...");
    return promise;
}

Answer

You are using async handler, thus your function probably completes before your connect() has a chance to execute.

To try to overcome the issue, you can use Promise as shown in AWS docs.