160 lines
8.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Сервис интеграции ПП Парус 8 с WEB API
Модуль ядра: сервер приложений
*/
//----------------------
// Подключение библиотек
//----------------------
const lg = require("./logger"); //Протоколирование работы
const db = require("./db_connector"); //Взаимодействие с БД
const oq = require("./out_queue"); //Прослушивание очереди исходящих сообщений
const { ServerError } = require("./server_errors"); //Типовая ошибка
const { validateObject } = require("./utils"); //Вспомогательные функции
const { SERR_COMMON, SERR_OBJECT_BAD_INTERFACE } = require("./constants"); //Общесистемные константы
const prmsAppSchema = require("../models/prms_app"); //Схема валидации параметров функций класса
//------------
// Тело модуля
//------------
//Класс сервера приложений
class ParusAppServer {
//конструктор класса
constructor() {
//Создаём логгер для протоколирования работы
this.logger = new lg.Logger();
//Подключение к БД
this.dbConn = null;
//Обработчик очереди исходящих
this.outQ = null;
//Флаг остановки сервера
this.bStopping = false;
//Список обслуживаемых сервисов
this.services = [];
//Привяжем методы к указателю на себя для использования в обработчиках событий
this.onDBConnected = this.onDBConnected.bind(this);
this.onDBDisconnected = this.onDBDisconnected.bind(this);
this.onOutQStarted = this.onOutQStarted.bind(this);
this.onOutQStopped = this.onOutQStopped.bind(this);
}
//При подключении к БД
async onDBConnected(connection) {
//Укажем логгеру, что можно писать в базу
this.logger.setDBConnector(this.dbConn, true);
//Сообщим, что подключились к БД
await this.logger.info("Сервер приложений подключен к БД");
//Считываем список сервисов
await this.logger.info("Запрашиваю информацию о сервисах...");
try {
this.services = await this.dbConn.getServices();
} catch (e) {
await this.logger.error("Ошибка получения списка сервисов: " + e.sCode + ": " + e.sMessage);
await this.stop();
return;
}
await this.logger.info("Список сервисов получен");
//Запускаем обслуживание очереди исходящих
await this.logger.info("Запуск обработчика очереди исходящих сообщений...");
try {
this.outQ.startProcessing(this.services);
} catch (e) {
await this.logger.error(
"Ошибка запуска обработчика очереди исходящих сообщений: " + e.sCode + ": " + e.sMessage
);
await this.stop();
return;
}
//Рапортуем, что запустились
await this.logger.info("Сервер приложений запущен");
}
//При отключении от БД
async onDBDisconnected() {
//Укажем логгеру, что писать в базу больше нельзя
this.logger.removeDBConnector();
//Сообщим, что отключились от БД
await this.logger.warn("Сервер приложений отключен от БД");
}
//При запуске обработчика исходящих сообщений
async onOutQStarted() {
//Сообщим, что запустили обработчик
await this.logger.info("Обработчик очереди исходящих сообщений запущен");
}
//При останове обработчика исходящих сообщений
async onOutQStopped() {
//Сообщим, что остановили обработчик
await this.logger.warn("Обработчик очереди исходящих сообщений остановлен");
//Отключение от БД
if (this.dbConn) {
if (this.dbConn.bConnected) {
await this.logger.warn("Отключение сервера приложений от БД...");
try {
await this.dbConn.disconnect();
process.exit(0);
} catch (e) {
await this.logger.error("Ошибка отключения от БД: " + e.sCode + ": " + e.sMessage);
process.exit(1);
}
} else {
process.exit(0);
}
} else {
process.exit(0);
}
}
//Инициализация сервера
async init(prms) {
await this.logger.info("Инициализация сервера приложений...");
//Проверяем структуру переданного объекта конфигурации
let sCheckResult = validateObject(prms, prmsAppSchema.init, "Параметры инициализации");
//Если настройки верны - будем стартовать
if (!sCheckResult) {
//Создаём подключение к БД
this.dbConn = new db.DBConnector({ connectSettings: prms.config.dbConnect });
//Создаём обработчик очереди исходящих
this.outQ = new oq.OutQueue({ outGoing: prms.config.outGoing, dbConn: this.dbConn, logger: this.logger });
//Скажем что инициализировали
await this.logger.info("Сервер приложений инициализирован");
} else {
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
}
}
//Запуск сервера
async run() {
//Рапортуем, что начали запуск
await this.logger.info("Запуск сервера приложений...");
//Проверим, что сервер успешно инициализирован
if (!this.logger || !this.dbConn || !this.outQ) {
throw new ServerError(SERR_COMMON, "Не пройдена инициализация");
}
//Включим прослушивание событий БД (для подключения/отключения логгера к БД)
this.dbConn.on(db.SEVT_DB_CONNECTOR_CONNECTED, this.onDBConnected);
this.dbConn.on(db.SEVT_DB_CONNECTOR_DISCONNECTED, this.onDBDisconnected);
//Включим прослушивание событий обработчика исходящих сообщений
this.outQ.on(oq.SEVT_OUT_QUEUE_STARTED, this.onOutQStarted);
this.outQ.on(oq.SEVT_OUT_QUEUE_STOPPED, this.onOutQStopped);
//Подключаемся к БД
await this.logger.info("Подключение сервера приложений к БД...");
await this.dbConn.connect();
}
//Останов сервера
async stop() {
if (!this.bStopping) {
//Установим флаг - остановка в процессе
this.bStopping = true;
//Сообщаем, что начала останов сервера
await this.logger.warn("Останов сервера приложений...");
//Останов обслуживания очереди исходящих
await this.logger.warn("Останов обработчика очереди исходящих сообщений...");
if (this.outQ) this.outQ.stopProcessing();
else this.onOutQStopped();
}
}
}
//------------------
// Интерфейс модуля
//------------------
exports.ParusAppServer = ParusAppServer;