Как изменить требуемое соединение после require()

#javascript #mysql #node.js #node-modules

#javascript #mysql #node.js #узел-модули

Вопрос:

В Node.js проект, над которым я сейчас работаю, сервер MySQL закрывает соединение после некоторого времени простоя. Я реализовал обработчик ошибок, который повторно подключается после такого рода потери соединения. Обработка ошибок работает, но я не могу найти способ получить файлы, для которых уже требовалось подключение, прежде чем использовать новое соединение.

Я уже пытался удалить кеш, но это не решает мою проблему.

 var mysql = require('mysql');
var mysqlConfig = require('./mysqlConfig');
var connection;

function handleDisconnect() {
    connection = mysql.createConnection(mysqlConfig.db);

    connection.connect((err) => {
        if (err) {
            console.log("error on connection to Database: "   err);
            setTimeout(handleDisconnect, 1000);
        }
    });

    connection.on('error', (err) => {
        delete require.cache[require.resolve('./db.js')]; //this module
        if (err.code === 'PROTOCOL_CONNECTION_LOST') {
            handleDisconnect();
        } else {
            throw err;
        }
    });
}

handleDisconnect();

module.exports = connection;
  

Вот пример файла, в котором требуется этот модуль:

 var db = require('../db');
var connector = {};

connector.GetStuff = function(query) {
    return new Promise((resolve, reject) => {
        let response = {};
        db.query(query, (error, results, fields) => {
            if (error) throw error;
            if (results amp;amp; results.length > 1) {
                response = results[0];
                resolve(response);
            }
        })
    })
}
  

Я хотел бы просто заменить объекты connection, которые требовались ранее, на новые. Но на самом деле мое приложение вылетает со следующей ошибкой:

Ошибка: не удается поставить запрос в очередь после фатальной ошибки.

Пожалуйста, не говорите мне просто открывать новое соединение для каждого запроса. это концепция, которую я не могу использовать из-за желания клиентов.

Ответ №1:

Хорошим решением было бы экспортировать не сам объект connection в первом файле, а некоторую оболочку или контейнер, содержимое которых периодически обновляется вашей функцией обработки ошибок соединения.

 class ConnectionContainer {
  setConnection(connection) {
    this.connection = connection;
  }

  getCurrentConnection() {
    return this.connection;
  }
}

const connectionContainer = new ConnectionContainer();

function handleDisconnect() {
    const connection = mysql.createConnection(mysqlConfig.db);

    connection.connect((err) => {
        if (err) {
            console.log("error on connection to Database: "   err);
            return setTimeout(handleDisconnect, 1000);
        } else {
          container.setConnection(connection); // set a new connection once it's connected
        }
    });

    connection.on('error', (err) => {
        delete require.cache[require.resolve('./db.js')]; // I don't think you need this anymore
        if (err.code === 'PROTOCOL_CONNECTION_LOST') {
            handleDisconnect();
        } else {
            throw err;
        }
    });
}

handleDisconnect();

module.exports.connectionContainer = connectionContainer;

// and in the connector file you could go like this:

const { connectionContainer } = require('../db'); // you might need a better name here for the file

//...
connectionContainer.getCurrentConnection().query(query, () => {});