Source: db/mysql.js

/**
 * @file A simple example module that exposes a getClient function.
 *
 * The client is replaced if it is disconnected.
 */

const mysql = require("mysql");

let client = mysql.createConnection({
  host: process.env.RDS_HOSTNAME,
  user: process.env.RDS_USERNAME,
  password: process.env.RDS_PASSWORD,
  port: process.env.RDS_PORT,
});

/**
 * Setup a client to automatically replace itself if it is disconnected.
 *
 * @param {Connection} client
 *   A MySQL connection instance.
 */
function replaceClientOnDisconnect(client) {
  client.on("error", function (err) {
    if (!err.fatal) {
      return;
    }

    if (err.code !== "PROTOCOL_CONNECTION_LOST") {
      throw err;
    }

    // client.config is actually a ConnectionConfig instance, not the original
    // configuration. For most situations this is fine, but if you are doing
    // something more advanced with your connection configuration, then
    // you should check carefully as to whether this is actually going to do
    // what you think it should do.
    client = mysql.createConnection(client.config);
    replaceClientOnDisconnect(client);
    client.connect(function (error) {
      if (error) {
        // Well, we tried. The database has probably fallen over.
        // That's fairly fatal for most applications, so we might as
        // call it a day and go home.
        //
        // For a real application something more sophisticated is
        // probably required here.
        process.exit(1);
      }
    });
  });
}

// And run this on every connection as soon as it is created.
replaceClientOnDisconnect(client);

function disconnectReconnect() {
  return new Promise((resolve, reject) => {
    client.end((error) => {
      if (!error) {
        client = mysql.createConnection({
          host: process.env.RDS_HOSTNAME,
          user: process.env.RDS_USERNAME,
          password: process.env.RDS_PASSWORD,
          port: process.env.RDS_PORT,
        });
        replaceClientOnDisconnect(client);
      }
      resolve();
    });
  });
}

/**
 * Every operation requiring a client should call this function, and not
 * hold on to the resulting client reference.
 *
 * @return {Connection}
 */
exports.getClient = async function () {
  return new Promise((resolve, reject) => {
    client.ping(function(err) {
      if (err) {
        disconnectReconnect().then(() => {
          resolve(client);
        });
      } else {
        resolve(client);
      }
    });
  });
};