Внедрение валидатора в модуле взаимодействия с БД

This commit is contained in:
Mikhail Chechnev 2018-11-26 20:50:44 +03:00
parent 2698ab6fee
commit 6360a86c54

View File

@ -11,19 +11,18 @@ const _ = require("lodash"); //Работа с массивами и объек
const EventEmitter = require("events"); //Обработчик пользовательских событий const EventEmitter = require("events"); //Обработчик пользовательских событий
const glConst = require("../core/constants"); //Глобальные константы const glConst = require("../core/constants"); //Глобальные константы
const { ServerError } = require("../core/server_errors"); //Типовая ошибка const { ServerError } = require("../core/server_errors"); //Типовая ошибка
const { makeModuleFullPath, checkObject, validateObject } = require("../core/utils"); //Вспомогательные функции const { makeModuleFullPath, validateObject } = require("../core/utils"); //Вспомогательные функции
const prmsDBConnectorSchema = require("../models/prms_db_connector"); //Схемы валидации параметров процедур модуля const prmsDBConnectorSchema = require("../models/prms_db_connector"); //Схемы валидации параметров процедур модуля
const intfDBConnectorModuleSchema = require("../models/intf_db_connector_module"); //Схема валидации интерфейса модуля взаимодействия с БД const intfDBConnectorModuleSchema = require("../models/intf_db_connector_module"); //Схема валидации интерфейса модуля взаимодействия с БД
const objServicesSchema = require("../models/obj_services"); //Схема валидации списка сервисов
const objQueueSchema = require("../models/obj_queue"); //Схема валидации сообщения очереди обмена
const objQueuesSchema = require("../models/obj_queues"); //Схема валидации списка сообщений очереди обмена
const objLogSchema = require("../models/obj_log"); //Схема валидации записи журнала
//---------- //----------
// Константы // Константы
//---------- //----------
//Состояния записей журнала работы сервиса
const NLOG_STATE_INF = 0; //Информация
const NLOG_STATE_WRN = 1; //Предупреждение
const NLOG_STATE_ERR = 2; //Ошибка
//Типовые коды ошибок работы с БД //Типовые коды ошибок работы с БД
const SERR_DB_CONNECT = "ERR_DB_CONNECT"; //Ошибка подключения к БД const SERR_DB_CONNECT = "ERR_DB_CONNECT"; //Ошибка подключения к БД
const SERR_DB_DISCONNECT = "ERR_DB_DISCONNECT"; //Ошибка отключения от БД const SERR_DB_DISCONNECT = "ERR_DB_DISCONNECT"; //Ошибка отключения от БД
@ -44,15 +43,7 @@ class DBConnector extends EventEmitter {
//создадим экземпляр родительского класса //создадим экземпляр родительского класса
super(); super();
//Проверяем структуру переданного объекта для подключения //Проверяем структуру переданного объекта для подключения
let sCheckResult = checkObject(prms, { let sCheckResult = validateObject(prms, prmsDBConnectorSchema.DBConnector, "Параметры конструктора");
fields: [
{ sName: "sUser", bRequired: true },
{ sName: "sPassword", bRequired: true },
{ sName: "sConnectString", bRequired: true },
{ sName: "sSessionModuleName", bRequired: true },
{ sName: "sConnectorModule", bRequired: false }
]
});
//Если структура объекта в норме //Если структура объекта в норме
if (!sCheckResult) { if (!sCheckResult) {
//Проверяем наличие модуля для работы с БД в настройках подключения //Проверяем наличие модуля для работы с БД в настройках подключения
@ -80,31 +71,40 @@ class DBConnector extends EventEmitter {
); );
} }
} else { } else {
throw new ServerError( throw new ServerError(glConst.SERR_OBJECT_BAD_INTERFACE, sCheckResult);
glConst.SERR_OBJECT_BAD_INTERFACE,
"Объект имеет недопустимый интерфейс: " + sCheckResult
);
} }
} }
//Подключиться к БД //Подключиться к БД
async connect() { async connect() {
//Подключаемся только если ещё не подключены
if (!this.bConnected) {
try { try {
//Подключаемся
this.connection = await this.connector.connect(this.connectSettings); this.connection = await this.connector.connect(this.connectSettings);
//Выставим внутренний флаг подключения
this.bConnected = true; this.bConnected = true;
//Расскажем всем, что подключились
this.emit(SEVT_DB_CONNECTOR_CONNECTED, this.connection); this.emit(SEVT_DB_CONNECTOR_CONNECTED, this.connection);
//Возвращаем подключение
return this.connection; return this.connection;
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_CONNECT, e.message); throw new ServerError(SERR_DB_CONNECT, e.message);
} }
} }
}
//Отключиться от БД //Отключиться от БД
async disconnect() { async disconnect() {
//Смысл отключаться есть только когда мы подключены, в противном случае - зачем тратить время
if (this.bConnected) { if (this.bConnected) {
try { try {
//Отключаемся
await this.connector.disconnect({ connection: this.connection }); await this.connector.disconnect({ connection: this.connection });
//Забываем подключение и удаляем флаги подключенности
this.connection = {}; this.connection = {};
this.bConnected = false; this.bConnected = false;
this.emit(SEVT_DB_CONNECTOR_DISCONNECTED, this.connection); //Расскажем всем, что отключились
this.emit(SEVT_DB_CONNECTOR_DISCONNECTED);
//Вернём ничего
return; return;
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_DISCONNECT, e.message); throw new ServerError(SERR_DB_DISCONNECT, e.message);
@ -113,25 +113,44 @@ class DBConnector extends EventEmitter {
} }
//Получить список сервисов //Получить список сервисов
async getServices() { async getServices() {
//Работаем только при наличии подключения
if (this.bConnected) { if (this.bConnected) {
try { try {
//Забираем список сервисов и декорируем его заготовками под список функций
let srvs = await this.connector.getServices({ connection: this.connection }); let srvs = await this.connector.getServices({ connection: this.connection });
srvs.forEach(s => {
s.functions = [];
});
//Валидируем его
let sCheckResult = validateObject({ services: srvs }, objServicesSchema.Services, "Список сервисов");
//Если в списке сервисов всё в порядке
if (!sCheckResult) {
//Забираем для каждого из сервисов список его функций
let srvsFuncs = srvs.map(async srv => { let srvsFuncs = srvs.map(async srv => {
const response = await this.connector.getServiceFunctions({ const response = await this.connector.getServiceFunctions({
connection: this.connection, connection: this.connection,
nServiceId: srv.nId nServiceId: srv.nId
}); });
let tmp = _.cloneDeep(srv); let tmp = _.cloneDeep(srv);
tmp.functions = [];
response.forEach(f => { response.forEach(f => {
tmp.functions.push(f); tmp.functions.push(f);
}); });
return tmp; return tmp;
}); });
//Ждём пока все функции вернутся
let res = await Promise.all(srvsFuncs); let res = await Promise.all(srvsFuncs);
//Валидируем финальный объект
sCheckResult = validateObject({ services: res }, objServicesSchema.Services, "Список сервисов");
//Если валидация не прошла
if (sCheckResult) throw new ServerError(glConst.SERR_OBJECT_BAD_INTERFACE, sCheckResult);
//Успешно - отдаём список сервисов
return res; return res;
} else {
throw new ServerError(glConst.SERR_OBJECT_BAD_INTERFACE, sCheckResult);
}
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_EXECUTE, e.message); if (e instanceof ServerError) throw e;
else throw new ServerError(SERR_DB_EXECUTE, e.message);
} }
} else { } else {
throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД"); throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД");
@ -139,32 +158,32 @@ class DBConnector extends EventEmitter {
} }
//Запись в журнал работы //Запись в журнал работы
async putLog(prms) { async putLog(prms) {
//Работаем только при наличии подключения
if (this.bConnected) { if (this.bConnected) {
//Проверяем структуру переданного объекта с параметрами для записи в журнал //Проверяем структуру переданного объекта с параметрами для записи в журнал
let sCheckResult = checkObject(prms, { let sCheckResult = validateObject(
fields: [ prms,
{ sName: "nLogState", bRequired: true }, prmsDBConnectorSchema.putLog,
{ sName: "sMsg", bRequired: false }, "Параметры функции записи в журнал работы"
{ sName: "nServiceId", bRequired: false }, );
{ sName: "nServiceFnId", bRequired: false },
{ sName: "nQueueId", bRequired: false }
]
});
//Если структура объекта в норме //Если структура объекта в норме
if (!sCheckResult) { if (!sCheckResult) {
try { try {
let logData = { connection: this.connection }; //Подготовим параметры для передачи в БД
_.extend(logData, prms); let logData = _.cloneDeep(prms);
logData.connection = this.connection;
//И выполним запись в журнал
let res = await this.connector.log(logData); let res = await this.connector.log(logData);
//Валидируем полученный ответ
sCheckResult = validateObject(res, objLogSchema.Log, "Добавленная запись журнала работы");
if (sCheckResult) throw new ServerError(glConst.SERR_OBJECT_BAD_INTERFACE, sCheckResult);
//Вернём добавленную запись
return res; return res;
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_EXECUTE, e.message); throw new ServerError(SERR_DB_EXECUTE, e.message);
} }
} else { } else {
throw new ServerError( throw new ServerError(glConst.SERR_OBJECT_BAD_INTERFACE, sCheckResult);
glConst.SERR_OBJECT_BAD_INTERFACE,
"Объект имеет недопустимый интерфейс: " + sCheckResult
);
} }
} else { } else {
throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД"); throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД");
@ -172,12 +191,15 @@ class DBConnector extends EventEmitter {
} }
//Запись информации в журнал работы //Запись информации в журнал работы
async putLogInf(sMsg, prms) { async putLogInf(sMsg, prms) {
let logData = {}; //Подготовим параметры для передачи в БД
_.extend(logData, prms); let logData = _.cloneDeep(prms);
logData.nLogState = NLOG_STATE_INF; //Выставим сообщение и тип записи журнала
logData.nLogState = objLogSchema.NLOG_STATE_INF;
logData.sMsg = sMsg; logData.sMsg = sMsg;
try { try {
//Выполним запись в журнал
let res = await this.putLog(logData); let res = await this.putLog(logData);
//Вернём добавленную запись
return res; return res;
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_EXECUTE, e.message); throw new ServerError(SERR_DB_EXECUTE, e.message);
@ -185,12 +207,15 @@ class DBConnector extends EventEmitter {
} }
//Запись предупреждения в журнал работы //Запись предупреждения в журнал работы
async putLogWrn(sMsg, prms) { async putLogWrn(sMsg, prms) {
let logData = {}; //Подготовим параметры для передачи в БД
_.extend(logData, prms); let logData = _.cloneDeep(prms);
logData.nLogState = NLOG_STATE_WRN; //Выставим сообщение и тип записи журнала
logData.nLogState = objLogSchema.NLOG_STATE_WRN;
logData.sMsg = sMsg; logData.sMsg = sMsg;
try { try {
//Выполним запись в журнал
let res = await this.putLog(logData); let res = await this.putLog(logData);
//Вернём добавленную запись
return res; return res;
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_EXECUTE, e.message); throw new ServerError(SERR_DB_EXECUTE, e.message);
@ -198,12 +223,15 @@ class DBConnector extends EventEmitter {
} }
//Запись ошибки в журнал работы //Запись ошибки в журнал работы
async putLogErr(sMsg, prms) { async putLogErr(sMsg, prms) {
let logData = {}; //Подготовим параметры для передачи в БД
_.extend(logData, prms); let logData = _.cloneDeep(prms);
logData.nLogState = NLOG_STATE_ERR; //Выставим сообщение и тип записи журнала
logData.nLogState = objLogSchema.NLOG_STATE_ERR;
logData.sMsg = sMsg; logData.sMsg = sMsg;
try { try {
//Выполним запись в журнал
let res = await this.putLog(logData); let res = await this.putLog(logData);
//Вернём добавленную запись
return res; return res;
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_EXECUTE, e.message); throw new ServerError(SERR_DB_EXECUTE, e.message);
@ -213,25 +241,33 @@ class DBConnector extends EventEmitter {
async getOutgoing(prms) { async getOutgoing(prms) {
if (this.bConnected) { if (this.bConnected) {
//Проверяем структуру переданного объекта с параметрами считывания очереди //Проверяем структуру переданного объекта с параметрами считывания очереди
let sCheckResult = checkObject(prms, { let sCheckResult = validateObject(
fields: [{ sName: "nPortionSize", bRequired: true }] prms,
}); prmsDBConnectorSchema.getOutgoing,
"Параметры функции считывания очереди"
);
//Если структура объекта в норме //Если структура объекта в норме
if (!sCheckResult) { if (!sCheckResult) {
try { try {
let res = await this.connector.getQueueOutgoing({ //Подготовим параметры для передачи в БД
connection: this.connection, let getQueueOutgoingData = _.cloneDeep(prms);
nPortionSize: prms.nPortionSize getQueueOutgoingData.connection = this.connection;
}); //Выполняем считывание из БД
let res = await this.connector.getQueueOutgoing(getQueueOutgoingData);
//Валидируем полученный ответ
sCheckResult = validateObject(
{ queues: res },
objQueuesSchema.Queues,
"Список сообщений очереди обмена"
);
if (sCheckResult) throw new ServerError(glConst.SERR_OBJECT_BAD_INTERFACE, sCheckResult);
//Вернём сообщения очереди обмена
return res; return res;
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_EXECUTE, e.message); throw new ServerError(SERR_DB_EXECUTE, e.message);
} }
} else { } else {
throw new ServerError( throw new ServerError(glConst.SERR_OBJECT_BAD_INTERFACE, sCheckResult);
glConst.SERR_OBJECT_BAD_INTERFACE,
"Объект имеет недопустимый интерфейс: " + sCheckResult
);
} }
} else { } else {
throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД"); throw new ServerError(SERR_DB_EXECUTE, "Нет подключения к БД");
@ -245,14 +281,19 @@ class DBConnector extends EventEmitter {
//Если структура объекта в норме //Если структура объекта в норме
if (!sCheckResult) { if (!sCheckResult) {
//Подготовим параметры //Подготовим параметры
let setStateData = { connection: this.connection }; let setStateData = _.cloneDeep(prms);
_.extend(setStateData, prms); setStateData.connection = this.connection;
//Исполняем действие в БД
try { try {
//Исполняем действие в БД
let res = await this.connector.setQueueState(setStateData); let res = await this.connector.setQueueState(setStateData);
//Валидируем полученный ответ
sCheckResult = validateObject(res, objQueueSchema.Queue, "Изменённое сообщение очереди обмена");
if (sCheckResult) throw new ServerError(glConst.SERR_OBJECT_BAD_INTERFACE, sCheckResult);
//Вернём измененную запись
return res; return res;
} catch (e) { } catch (e) {
throw new ServerError(SERR_DB_EXECUTE, e.message); if (e instanceof ServerError) throw e;
else throw new ServerError(SERR_DB_EXECUTE, e.message);
} }
} else { } else {
throw new ServerError(glConst.SERR_OBJECT_BAD_INTERFACE, sCheckResult); throw new ServerError(glConst.SERR_OBJECT_BAD_INTERFACE, sCheckResult);
@ -267,9 +308,6 @@ class DBConnector extends EventEmitter {
// Интерфейс модуля // Интерфейс модуля
//----------------- //-----------------
exports.NLOG_STATE_INF = NLOG_STATE_INF;
exports.NLOG_STATE_WRN = NLOG_STATE_WRN;
exports.NLOG_STATE_ERR = NLOG_STATE_ERR;
exports.SERR_DB_CONNECT = SERR_DB_CONNECT; exports.SERR_DB_CONNECT = SERR_DB_CONNECT;
exports.SERR_DB_DISCONNECT = SERR_DB_DISCONNECT; exports.SERR_DB_DISCONNECT = SERR_DB_DISCONNECT;
exports.SERR_DB_EXECUTE = SERR_DB_EXECUTE; exports.SERR_DB_EXECUTE = SERR_DB_EXECUTE;