ЦИТК-659 - Возможность работы нескольких серверов параллельно

This commit is contained in:
Dollerino 2025-05-29 17:43:21 +03:00
parent 0e2a5b6bd2
commit 9ba6d2771f
6 changed files with 78 additions and 156 deletions

View File

@ -177,7 +177,7 @@ class ParusAppServer {
if (this.dbConn.bConnected) { if (this.dbConn.bConnected) {
await this.logger.warn("Отключение сервера приложений от БД..."); await this.logger.warn("Отключение сервера приложений от БД...");
try { try {
await this.dbConn.disconnect({ bServerClose: true }); await this.dbConn.disconnect();
} catch (e) { } catch (e) {
await this.logger.error(`Ошибка отключения от БД: ${e.sCode}: ${e.sMessage}`); await this.logger.error(`Ошибка отключения от БД: ${e.sCode}: ${e.sMessage}`);
} }
@ -213,7 +213,8 @@ class ParusAppServer {
nPoolMax: prms.config.inComing.nPoolMax, nPoolMax: prms.config.inComing.nPoolMax,
nPoolIncrement: prms.config.inComing.nPoolIncrement, nPoolIncrement: prms.config.inComing.nPoolIncrement,
nMaxWorkers: prms.config.outGoing.nMaxWorkers nMaxWorkers: prms.config.outGoing.nMaxWorkers
} },
bServer: true
}); });
//Создаём модуль рассылки уведомлений //Создаём модуль рассылки уведомлений
this.notifier = new ntf.Notifier({ logger: this.logger, mail: prms.config.mail }); this.notifier = new ntf.Notifier({ logger: this.logger, mail: prms.config.mail });
@ -275,7 +276,7 @@ class ParusAppServer {
this.srvAvlCtrl.on(sac.SEVT_SERVICE_AVAILABLE_CONTROLLER_STOPPED, this.onServiceACStopped); this.srvAvlCtrl.on(sac.SEVT_SERVICE_AVAILABLE_CONTROLLER_STOPPED, this.onServiceACStopped);
//Подключаемся к БД //Подключаемся к БД
await this.logger.info("Подключение сервера приложений к БД..."); await this.logger.info("Подключение сервера приложений к БД...");
await this.dbConn.connect({ bServerStart: true }); await this.dbConn.connect();
} }
//Останов сервера //Останов сервера
async stop(terminateTimeout) { async stop(terminateTimeout) {

View File

@ -74,6 +74,7 @@ class DBConnector extends EventEmitter {
this.connection = null; this.connection = null;
this.bConnected = false; this.bConnected = false;
this.nExsSrv = null; this.nExsSrv = null;
this.bServer = prms.bServer === true ? true : false;
} else { } else {
throw new ServerError(SERR_MODULES_NO_MODULE_SPECIFIED, "Не указано имя подключаемого модуля-коннектора!"); throw new ServerError(SERR_MODULES_NO_MODULE_SPECIFIED, "Не указано имя подключаемого модуля-коннектора!");
} }
@ -95,23 +96,36 @@ class DBConnector extends EventEmitter {
} }
} }
//Подключиться к БД //Подключиться к БД
async connect(prms) { async connect() {
//Подключаемся только если ещё не подключены //Подключаемся только если ещё не подключены
if (!this.bConnected) { if (!this.bConnected) {
//Проверяем структуру переданного объекта с параметрами для подключения к БД
let sCheckResult = validateObject(prms, prmsDBConnectorSchema.connect, "Параметры функции подключения к БД");
//Если структура объекта в норме
if (!sCheckResult) {
try { try {
//Подготовим параметры для передачи в БД
let connectData = _.cloneDeep(prms);
connectData.connectSettings = this.connectSettings;
//Подключаемся //Подключаемся
let res = await this.connector.connect(connectData); this.connection = await this.connector.connect(this.connectSettings);
//Сохраняем информацию о подключении //Если это запуск сервиса интеграции
this.connection = res.pool; if (this.bServer) {
//Сохраняем информацию о сервере интеграции //Проверяем общие условия запуска
this.nExsSrv = res.nExsSrv; await this.connector.checkAppStart({
bControlSystemVersion: this.connectSettings.bControlSystemVersion,
sRelease: this.connectSettings.sRelease,
nWorkers: this.connectSettings.nMaxWorkers,
sServerName: this.connectSettings.exsSrv.sServerName,
sModuleName: this.connectSettings.exsSrv.sServerName
? `${this.connectSettings.sSessionAppName}$${this.connectSettings.exsSrv.sServerName}`
: this.connectSettings.sSessionAppName,
connection: this.connection
});
//Если сервис интеграции разделяется на сервера
if (this.connectSettings.exsSrv.sServerName) {
//Инициализируем информацию о сервере интеграции
this.nExsSrv = await this.connector.initServer({
sServerName: this.connectSettings.exsSrv.sServerName,
sServerIP: this.connectSettings.exsSrv.sServerIP,
nMaxWorkers: this.connectSettings.nMaxWorkers,
connection: this.connection
});
}
}
//Выставим внутренний флаг подключения //Выставим внутренний флаг подключения
this.bConnected = true; this.bConnected = true;
//Расскажем всем, что подключились //Расскажем всем, что подключились
@ -121,26 +135,20 @@ class DBConnector extends EventEmitter {
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_CONNECT, e.message); throw new ServerError(SERR_DB_CONNECT, e.message);
} }
} else {
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
}
} }
} }
//Отключиться от БД //Отключиться от БД
async disconnect(prms) { async disconnect() {
//Смысл отключаться есть только когда мы подключены, в противном случае - зачем тратить время //Смысл отключаться есть только когда мы подключены, в противном случае - зачем тратить время
if (this.bConnected) { if (this.bConnected) {
//Проверяем структуру переданного объекта с параметрами для подключения к БД
let sCheckResult = validateObject(prms, prmsDBConnectorSchema.disconnect, "Параметры функции отключения от БД");
//Если структура объекта в норме
if (!sCheckResult) {
try { try {
//Подготовим параметры для передачи в БД //Если указана информация о сервере и это закрытие сервиса интеграции
let disconnectData = _.cloneDeep(prms); if (this.nExsSrv && this.bServer) {
disconnectData.connection = this.connection; //Очищаем информацию о сервере
disconnectData.nExsSrv = this.nExsSrv; await this.connector.clearServer({ nExsSrv: this.nExsSrv, connection: this.connection });
}
//Отключаемся //Отключаемся
await this.connector.disconnect(disconnectData); await this.connector.disconnect({ connection: this.connection });
//Забываем подключение и удаляем флаги подключенности //Забываем подключение и удаляем флаги подключенности
this.connection = null; this.connection = null;
this.bConnected = false; this.bConnected = false;
@ -151,9 +159,6 @@ class DBConnector extends EventEmitter {
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_DISCONNECT, e.message); throw new ServerError(SERR_DB_DISCONNECT, e.message);
} }
} else {
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
}
} }
} }
//Получить список сервисов //Получить список сервисов

View File

@ -604,7 +604,7 @@ const processTask = async prms => {
logger.removeDBConnector(); logger.removeDBConnector();
}); });
//Подключаемся к БД //Подключаемся к БД
await dbConn.connect({ bServerStart: false }); await dbConn.connect();
//Считываем запись очереди //Считываем запись очереди
q = await dbConn.getQueue({ nQueueId: prms.task.nQueueId }); q = await dbConn.getQueue({ nQueueId: prms.task.nQueueId });
//Далее работаем от статуса считанной записи //Далее работаем от статуса считанной записи
@ -709,12 +709,12 @@ const processTask = async prms => {
} }
} }
//Отключаемся от БД //Отключаемся от БД
if (dbConn) await dbConn.disconnect({ bServerClose: false }); if (dbConn) await dbConn.disconnect();
//Отправляем успех //Отправляем успех
sendOKResult(); sendOKResult();
} catch (e) { } catch (e) {
//Отключаемся от БД //Отключаемся от БД
if (dbConn) await dbConn.disconnect({ bServerClose: false }); if (dbConn) await dbConn.disconnect();
//Отправляем ошибку //Отправляем ошибку
if (e instanceof ServerError && e.sCode == SERR_UNAUTH) sendUnAuthResult(); if (e instanceof ServerError && e.sCode == SERR_UNAUTH) sendUnAuthResult();
else sendErrorResult({ sMessage: makeErrorText(e) }); else sendErrorResult({ sMessage: makeErrorText(e) });

View File

@ -74,32 +74,6 @@ exports.DBConnector = new Schema({
} }
}); });
//Схема валидации параметров функции подключения к БД
exports.connect = new Schema({
//Признак запуска сервера интеграции
bServerStart: {
type: Boolean,
required: true,
message: {
type: path => `Признак запуска сервера интеграции (${path}) имеет некорректный тип данных (ожидалось - Boolean)`,
required: path => `Не указан признак запуска сервера интеграции (${path})`
}
}
});
//Схема валидации параметров функции отключения от БД
exports.disconnect = new Schema({
//Признак выключения сервера интеграции
bServerClose: {
type: Boolean,
required: true,
message: {
type: path => `Признак выключения сервера интеграции (${path}) имеет некорректный тип данных (ожидалось - Boolean)`,
required: path => `Не указан признак выключения сервера интеграции (${path})`
}
}
});
//Схема валидации параметров функции получения списка функций сервиса //Схема валидации параметров функции получения списка функций сервиса
exports.getServiceFunctions = new Schema({ exports.getServiceFunctions = new Schema({
//Идентификатор сервиса //Идентификатор сервиса

View File

@ -185,24 +185,20 @@ const clearServer = async prms => {
//Подключение к БД //Подключение к БД
const connect = async prms => { const connect = async prms => {
try { try {
//Инициализируем результат подключения
let connection = { pool: null, nExsSrv: null };
//Определяем наименование модуля сессии //Определяем наименование модуля сессии
let moduleName = prms.connectSettings.exsSrv.sServerName let moduleName = prms.exsSrv.sServerName ? `${prms.sSessionAppName}$${prms.exsSrv.sServerName}` : prms.sSessionAppName;
? `${prms.connectSettings.sSessionAppName}$${prms.connectSettings.exsSrv.sServerName}`
: prms.connectSettings.sSessionAppName;
//Создаем пул подключения //Создаем пул подключения
connection.pool = await oracledb.createPool({ let pool = await oracledb.createPool({
user: prms.connectSettings.sUser, user: prms.sUser,
password: prms.connectSettings.sPassword, password: prms.sPassword,
connectString: prms.connectSettings.sConnectString, connectString: prms.sConnectString,
queueTimeout: 600000, queueTimeout: 600000,
poolMin: prms.connectSettings.nPoolMin ? prms.connectSettings.nPoolMin : 4, poolMin: prms.nPoolMin ? prms.nPoolMin : 4,
poolMax: prms.connectSettings.nPoolMax ? prms.connectSettings.nPoolMax : 4, poolMax: prms.nPoolMax ? prms.nPoolMax : 4,
poolIncrement: prms.connectSettings.nPoolIncrement ? prms.connectSettings.nPoolIncrement : 0, poolIncrement: prms.nPoolIncrement ? prms.nPoolIncrement : 0,
sessionCallback: (connection, requestedTag, callback) => { sessionCallback: (connection, requestedTag, callback) => {
connection.module = moduleName; connection.module = moduleName;
connection.execute(`ALTER SESSION SET CURRENT_SCHEMA=${prms.connectSettings.sSchema}`).then( connection.execute(`ALTER SESSION SET CURRENT_SCHEMA=${prms.sSchema}`).then(
r => { r => {
callback(null, connection); callback(null, connection);
}, },
@ -212,29 +208,7 @@ const connect = async prms => {
); );
} }
}); });
//Если это запуск сервиса интеграции return pool;
if (prms.bServerStart) {
//Проверяем общие условия запуска
await checkAppStart({
bControlSystemVersion: prms.connectSettings.bControlSystemVersion,
sRelease: prms.connectSettings.sRelease,
nWorkers: prms.connectSettings.nMaxWorkers,
sServerName: prms.connectSettings.exsSrv.sServerName,
sModuleName: moduleName,
connection: connection.pool
});
//Если сервис интеграции разделяется на сервера
if (prms.connectSettings.exsSrv.sServerName) {
//Инициализируем информацию о сервере интеграции
connection.nExsSrv = await initServer({
sServerName: prms.connectSettings.exsSrv.sServerName,
sServerIP: prms.connectSettings.exsSrv.sServerIP,
nMaxWorkers: prms.connectSettings.nMaxWorkers,
connection: connection.pool
});
}
}
return connection;
} catch (e) { } catch (e) {
throw new Error(e.message); throw new Error(e.message);
} }
@ -243,11 +217,6 @@ const connect = async prms => {
//Отключение от БД //Отключение от БД
const disconnect = async prms => { const disconnect = async prms => {
try { try {
//Если указана информация о сервере и это закрытие сервиса интеграции
if (prms.nExsSrv && prms.bServerClose) {
//Очищаем информацию о сервере
await clearServer({ nExsSrv: prms.nExsSrv, connection: prms.connection });
}
//Отключаем от базы данных //Отключаем от базы данных
await prms.connection.close(NPOOL_DRAIN_TIME); await prms.connection.close(NPOOL_DRAIN_TIME);
return; return;
@ -551,6 +520,9 @@ exports.DT_CLOB = DT_CLOB;
exports.DT_BLOB = DT_BLOB; exports.DT_BLOB = DT_BLOB;
exports.DT_CURSOR = DT_CURSOR; exports.DT_CURSOR = DT_CURSOR;
exports.executeStored = executeStored; exports.executeStored = executeStored;
exports.checkAppStart = checkAppStart;
exports.initServer = initServer;
exports.clearServer = clearServer;
exports.connect = connect; exports.connect = connect;
exports.disconnect = disconnect; exports.disconnect = disconnect;
exports.getServices = getServices; exports.getServices = getServices;

View File

@ -188,14 +188,8 @@ const clearServer = async prms => {
//Подключение к БД //Подключение к БД
const connect = async prms => { const connect = async prms => {
try { try {
//Инициализируем результат подключения
let connection = { pool: null, nExsSrv: null };
//Определяем наименование модуля сессии
let moduleName = prms.connectSettings.exsSrv.sServerName
? `${prms.connectSettings.sSessionAppName}$${prms.connectSettings.exsSrv.sServerName}`
: prms.connectSettings.sSessionAppName;
//Создаем пул подключения //Создаем пул подключения
connection.pool = new pg.Pool({ let pool = new pg.Pool({
connectionString: `postgres://${prms.connectSettings.sUser}:${prms.connectSettings.sPassword}@${prms.connectSettings.sConnectString}`, connectionString: `postgres://${prms.connectSettings.sUser}:${prms.connectSettings.sPassword}@${prms.connectSettings.sConnectString}`,
connectionTimeoutMillis: 600000, connectionTimeoutMillis: 600000,
min: prms.connectSettings.nPoolMin ? prms.connectSettings.nPoolMin : 4, min: prms.connectSettings.nPoolMin ? prms.connectSettings.nPoolMin : 4,
@ -204,29 +198,7 @@ const connect = async prms => {
pool.on("acquire", async client => { pool.on("acquire", async client => {
await client.query(`select ALTER_SESSION_SET_SCHEMA($1);`, [prms.connectSettings.sSchema]); await client.query(`select ALTER_SESSION_SET_SCHEMA($1);`, [prms.connectSettings.sSchema]);
}); });
//Если это запуск сервиса интеграции return pool;
if (prms.bServerStart) {
//Проверяем общие условия запуска
await checkAppStart({
bControlSystemVersion: prms.connectSettings.bControlSystemVersion,
sRelease: prms.connectSettings.sRelease,
nWorkers: prms.connectSettings.nMaxWorkers,
sServerName: prms.connectSettings.exsSrv.sServerName,
sModuleName: moduleName,
connection: connection.pool
});
//Если сервис интеграции разделяется на сервера
if (prms.connectSettings.exsSrv.sServerName) {
//Инициализируем информацию о сервере интеграции
connection.nExsSrv = await initServer({
sServerName: prms.connectSettings.exsSrv.sServerName,
sServerIP: prms.connectSettings.exsSrv.sServerIP,
nMaxWorkers: prms.connectSettings.nMaxWorkers,
connection: connection.pool
});
}
}
return connection;
} catch (e) { } catch (e) {
throw new Error(e.message); throw new Error(e.message);
} }
@ -235,11 +207,6 @@ const connect = async prms => {
//Отключение от БД //Отключение от БД
const disconnect = async prms => { const disconnect = async prms => {
try { try {
//Если указана информация о сервере и это закрытие сервиса интеграции
if (prms.nExsSrv && prms.bServerClose) {
//Очищаем информацию о сервере
await clearServer({ nExsSrv: prms.nExsSrv, connection: prms.connection });
}
await prms.connection.end(); await prms.connection.end();
} catch (e) { } catch (e) {
throw new Error(e.message); throw new Error(e.message);
@ -540,6 +507,9 @@ exports.DT_CLOB = DT_CLOB;
exports.DT_BLOB = DT_BLOB; exports.DT_BLOB = DT_BLOB;
exports.DT_CURSOR = DT_CURSOR; exports.DT_CURSOR = DT_CURSOR;
exports.executeStored = executeStored; exports.executeStored = executeStored;
exports.checkAppStart = checkAppStart;
exports.initServer = initServer;
exports.clearServer = clearServer;
exports.connect = connect; exports.connect = connect;
exports.disconnect = disconnect; exports.disconnect = disconnect;
exports.getServices = getServices; exports.getServices = getServices;