Maxlistenersexceeded Warning в приложении Node JS Express

#node.js #mongoose #amazon-elastic-beanstalk #dialogflow-es #sigint

#node.js #мангуст #amazon-elastic-beanstalk #диалоговые потоки #sigint

Вопрос:

Я развертываю приложение Node JS Express для веб-интерфейса Dialogflow на AWS Elastic Beanstalk. Приложение использует mongoose для сохранения данных в MongoDB. Есть четыре события подключения (подключено / отключено / ошибка / завершение процесса). В журнале моей консоли выдается следующее предупреждение: MaxListenersExceededWarning: обнаружена возможная утечка памяти EventEmitter. в [NativeConnection] добавлено 11 подключенных прослушивателей. Используйте emitter.setMaxListeners() для увеличения лимита. Я не хочу подавлять предупреждение, добавляя больше прослушивателей событий, поскольку я не думаю, что требуется больше прослушивателей. Когда я внимательно изучаю журнал, я вижу, что приложение node никогда не завершается, и событие завершения процесса никогда не запускается. Ссылка на журнал находится в конце этого поста. Ниже приведен код, который я использую для различных событий. Обратите внимание, что события запускаются в двух областях в коде webhook: (1) в намерении приветствия по умолчанию (для раннего подключения к БД, чтобы гарантировать, что данные будут быстро отправлены в БД позже, когда это необходимо) и (2) в функции database_request, которая вызывается в самом последнем намерении, когда пользователь подтверждает свой выбор.

Я подозреваю, что в коде для события завершения процесса может быть ошибка, которая удаляет слушателей в конце. Но два сообщения в коде события завершения процесса никогда не регистрируются. Кто-нибудь может сообщить мне, что не так с моим кодом? Заранее спасибо.

 function DefaultWelcomeIntent(agent){
  console.log("mongoose.connection.readyState: ",mongoose.connection.readyState);
  if (mongoose.connection.readyState !== 1) {
    mongoose.connect(dbURI,{ useUnifiedTopology: true ,useNewUrlParser: true}, () => {
    console.log("Mongoose state: ", mongoose.connection.readyState);
  })
    .catch((e) => {
      console.log("catch error: ", e);
    });
  }

  mongoose.connection.on('connected', function () {
    console.log("Mongoose is connected");
  });

  mongoose.connection.on('disconnected', function () {
    console.log("Mongoose is disconnected");
    process.exit(1);
  });

  mongoose.connection.on('error', function (err) {//any error
    console.log('Mongoose connection error: ', err);
    process.exit(1);
  });

  process.on('SIGINT', function () {
    console.log("app is terminating");
    mongoose.connection.close(function () {
      console.log('Mongoose default connection closed');
      mongoose.connection.removeAllListeners();  
      process.exit(0); // terminates a node js process with 'success code'.
    });
  });

// some additional code in welcome intent to respond to user
}

function database_request1(context_parameters) {  
  if (mongoose.connection.readyState !== 1) {
    mongoose.connect(dbURI, { useUnifiedTopology: true ,useNewUrlParser: true},() => {
      console.log("Mongoose state: ", mongoose.connection.readyState);
  })
      .catch((e) => {
        console.log("catch error: ", e);
      });
  }

  mongoose.connection.on('connected', function () {
    console.log("Mongoose is connected");
  });

  mongoose.connection.on('disconnected', function () {
    console.log("Mongoose is disconnected");
    process.exit(1);
  });

  mongoose.connection.on('error', function (err) {
    console.log('Mongoose connection error: ', err);
    process.exit(1);
  });

  process.on('SIGINT', function () {
    console.log("app is terminating");
    mongoose.connection.close(function () {
      console.log('Mongoose default connection closed');
      mongoose.connection.removeAllListeners(); 
      process.exit(0); 
    });
  });
// some additional code to save data to DB
}
  

Скриншот журнала

Комментарии:

1. Где этот код расположен в остальной части вашего кода? На первый взгляд, это звучит так, как будто оно вызывается каждый раз, когда вы получаете запрос Dialogflow или что-то подобное.

2. @Prisoner спасибо за ваш комментарий. Я обновил свой приведенный выше код, чтобы показать, где вызываются эти события. Они вызываются только в двух областях: в намерении приветствия и в функции, которая вызывается в конце для сохранения данных в DB.

3. Вы не должны устанавливать новое подключение к базе данных при каждом запросе. Вместо этого вы должны создать подключение к базе данных один раз при запуске, а затем использовать это же соединение в остальной части вашего кода. Ваш драйвер базы данных обычно обрабатывает пул соединений и т.д. Внутри

4. @slebetman спасибо, я обновил приведенный выше код, чтобы показать, что я создаю соединение только при запуске, а затем в конце, когда данные передаются в базу данных.