Search code examples
mysqlnode.jsconnection-pooling

Node MySQL Connection Pool - wait for database to start


How do I check if a MySQL database is ready for some queries from a Node MySQL Connection Pool?

I have a Docker environment consisting of thee containers:

  • container 1: web server
  • container 2: api
  • container 3: database

The database container runs a MySQL database. The api container connects to that database. All three containers are started at the same time. The web server container is up after 0,5s. The api container is up after 2s. The database server is up after 20s.

Currently, the api tries to access the tables of the database before the database is up and running. This leads to errors like connection refused. The following code segment always ends up with the message "Error querying database!" when the MySQL database is not yet up:

const sql: string = 'SELECT * FROM sometable;';
MySQL.createPool({
    connectionLimit: 10,
    acquireTimeout: 30000,
    waitForConnections: true,
    database: 'mydatabase',
    host: 'localhost',
    multipleStatements: true,
    password: 'mypassword',
    user: 'root',
}).query(sql, (err, result) => {
    if (result) {
        console.log('Successfully queried database.');
    } else {
        console.log('Error querying database!');
    }
});

Versions in use:

OS: Ubuntu 19.10
Node: v13.6.0
MySQL (Node API): "@types/mysql": "2.15.8" and "mysql": "2.17.1"
MySQL (Docker Database): mysql:5.7.28
TypeScript: 3.7.4

I would like to check (and wait) the database readiness out of the api, possibly using the Connection Pool I use for queries. Is that possible?


Solution

  • Retry to connect with setTimeout():

    (answer in Javascript rather than typescript)

    'use strict';
    
    const dbpool = require('mysql').createPool({
        connectionLimit: 10,
        acquireTimeout: 30000,
        waitForConnections: true,
        database: 'mydatabase',
        host: 'localhost',
        multipleStatements: true,
        password: 'mypassword',
        user: 'root',
    });
    
    const sql = 'SELECT * FROM sometable;';
    
    const attemptConnection = () =>
      dbpool.getConnection((err, connection) => {
      if (err) {
        console.log('error connecting. retrying in 1 sec');
        setTimeout(attemptConnection, 1000);
      } else {
        connection.query(sql, (errQuery, results) => {
          connection.release();
          if (errQuery) {
            console.log('Error querying database!');
          } else {
            console.log('Successfully queried database.');
          }
        });
      }
    });
    
    attemptConnection();
    

    Here is my test run:

    $ sudo service mysql stop; node test.js & sudo service mysql start
    [1] 24737
    error connecting. retrying in 1 sec
    error connecting. retrying in 1 sec
    $ Successfully queried database.
    

    FYI, The program never ends because it needs dbpool.end();