Формирование модульной структуры, логгер, коннектор к БД, утиля

This commit is contained in:
Mikhail Chechnev 2018-11-01 20:30:16 +03:00
parent 18d954d361
commit 66e58b66c2
9 changed files with 391 additions and 56 deletions

View File

@ -1,5 +1,28 @@
module.exports = {
/*
Сервис интеграции ПП Парус 8 с WEB API
Конфигурация сервера приложений
*/
//------------
// Тело модуля
//------------
//Параметры подключения к БД
let dbConnect = {
//Пользователь БД
user: "parus",
//Пароль пользователя БД
password: "parus",
connectString: "DEMOP_CITKSERV"
//Строка подключения к БД
connectString: "DEMOP_CITKSERV",
//Модуль обслуживания БД
module: "parus_db.js"
};
//-----------------
// Интерфейс модуля
//-----------------
module.exports = {
dbConnect
};

20
core/constants.js Normal file
View File

@ -0,0 +1,20 @@
/*
Сервис интеграции ПП Парус 8 с WEB API
Модуль ядра: глобавльные константы
*/
//-----------------
// Интерфейс модуля
//-----------------
//Путь к модулям
exports.MODULES_PATH_CORE = "@core"; //Модули ядра
exports.MODULES_PATH_EX = "@modules"; //Дополнительные пользовательские модули
//Типовые коды ошибок подключения модулей
exports.ERR_MODULES_NO_MODULE_SPECIFIED = "ERR_MODULES_NO_MODULE_SPECIFIED"; //Не указан подключаемый модуль
exports.ERR_MODULES_BAD_INTERFACE = "ERR_MODULES_BAD_INTERFACE"; //Ошибочный интерфейс подключаемого модуля
//Типовые коды ошибок работы с БД
exports.ERR_DB_CONNECT = "ERR_DB_CONNECT"; //Ошибка подключения к БД
exports.ERR_DB_DISCONNECT = "ERR_DB_DISCONNECT"; //Ошибка отключения от БД

72
core/db_connector.js Normal file
View File

@ -0,0 +1,72 @@
/*
Сервис интеграции ПП Парус 8 с WEB API
Модуль ядра: взаимодействие с БД
*/
//----------------------
// Подключение библиотек
//----------------------
const _ = require("lodash"); //Работа с массивами и объектами
const glConst = require("@core/constants.js"); //Глобальные константы
const { checkModuleInterface, makeModuleFullPath } = require("@core/utils.js"); //Вспомогательные функции
const { ServerError } = require("@core/server_errors.js"); //Типовая ошибка
//------------
// Тело модуля
//------------
class DBConnector {
//Конструктор
constructor(dbConnect) {
//Проверяем наличие модуля для работы с БД в настройках подключения
if (dbConnect.module) {
//Подключим модуль
this.connector = require(makeModuleFullPath(dbConnect.module));
//Проверим его интерфейс
if (!checkModuleInterface(this.connector, { functions: ["connect", "disconnect", "execute"] })) {
throw new ServerError(
glConst.ERR_MODULES_BAD_INTERFACE,
"Модуль " + dbConnect.module + " реализует неверный интерфейс!"
);
}
//Всё успешно - сохраним настройки подключения
this.connectSettings = {};
_.extend(this.connectSettings, dbConnect);
//Инициализируем остальные свойства
this.connection = {};
} else {
throw new ServerError(
glConst.ERR_MODULES_NO_MODULE_SPECIFIED,
"Не указано имя подключаемого модуля-коннектора!"
);
}
}
//Подключиться к БД
async connect() {
try {
this.connection = await this.connector.connect(this.connectSettings);
return this.connection;
} catch (e) {
throw new ServerError(glConst.ERR_DB_CONNECT, e.message);
}
}
//Отключиться от БД
async disconnect() {
try {
await this.connector.disconnect(this.connection);
this.connection = {};
return;
} catch (e) {
throw new ServerError(glConst.ERR_DB_DISCONNECT, e.message);
}
}
//Исполнить запрос
async execute() {}
}
//-----------------
// Интерфейс модуля
//-----------------
exports.DBConnector = DBConnector;

87
core/logger.js Normal file
View File

@ -0,0 +1,87 @@
/*
Сервис интеграции ПП Парус 8 с WEB API
Модуль ядра: протоколирование работы
*/
//------------
// Тело модуля
//------------
//Тип сообщения протокола - ошибка
const LOGGER_MESSAGE_TYPE_ERROR = "ERROR";
//Тип сообщения протокола - предупреждение
const LOGGER_MESSAGE_TYPE_WARN = "WARN";
//Тип сообщения протокола - информация
const LOGGER_MESSAGE_TYPE_INFO = "INFO";
//Сообщение протокола
class LoggerMessage {
//Конструктор класса
constructor(type, message) {
this.type = type;
this.message = message;
}
}
//Класс управления протоколом
class Logger {
//Конструктор класса
constructor() {}
//Протоколирование ошибки
error(msg) {
this.log(new LoggerMessage(LOGGER_MESSAGE_TYPE_ERROR, msg));
}
//Протоколирование предупреждения
warn(msg) {
this.log(new LoggerMessage(LOGGER_MESSAGE_TYPE_WARN, msg));
}
//Протоколирование информации
info(msg) {
this.log(new LoggerMessage(LOGGER_MESSAGE_TYPE_INFO, msg));
}
//Протоколирование
log(loggerMessage) {
let message = "";
let prefix = "LOG MESSAGE";
let colorPattern = "";
//Конструируем сообщение
if (loggerMessage instanceof LoggerMessage) {
switch (loggerMessage.type) {
case LOGGER_MESSAGE_TYPE_ERROR: {
prefix = "ERROR";
colorPattern = "\x1b[31m%s\x1b[0m%s";
break;
}
case LOGGER_MESSAGE_TYPE_WARN: {
prefix = "WARNING";
colorPattern = "\x1b[33m%s\x1b[0m%s";
break;
}
case LOGGER_MESSAGE_TYPE_INFO: {
prefix = "INFORMATION";
colorPattern = "\x1b[32m%s\x1b[0m%s";
break;
}
default:
break;
}
message = loggerMessage.message;
} else {
message = loggerMessage;
}
//Выдаём сообщение
console.log(colorPattern, prefix + ": ", message);
}
}
//-----------------
// Интерфейс модуля
//-----------------
exports.LOGGER_MESSAGE_TYPE_ERROR = LOGGER_MESSAGE_TYPE_ERROR;
exports.LOGGER_MESSAGE_TYPE_WARN = LOGGER_MESSAGE_TYPE_WARN;
exports.LOGGER_MESSAGE_TYPE_INFO = LOGGER_MESSAGE_TYPE_INFO;
exports.LoggerMessage = LoggerMessage;
exports.Logger = Logger;

23
core/server_errors.js Normal file
View File

@ -0,0 +1,23 @@
/*
Сервис интеграции ПП Парус 8 с WEB API
Модуль ядра: ошибки системы
*/
//------------
// Тело модуля
//------------
//Общая ошибка системы
class ServerError extends Error {
//Конструктор
constructor(code, message) {
super(message);
this.code = code;
}
}
//-----------------
// Интерфейс модуля
//-----------------
exports.ServerError = ServerError;

78
core/utils.js Normal file
View File

@ -0,0 +1,78 @@
/*
Сервис интеграции ПП Парус 8 с WEB API
Модуль ядра: вспомогательные функции
*/
//----------------------
// Подключение библиотек
//----------------------
const { MODULES_PATH_EX } = require("@core/constants.js"); //Глобавльные константы системы
//------------
// Тело модуля
//------------
//Проверка на функцию
const isFunction = functionToCheck => {
return functionToCheck && {}.toString.call(functionToCheck) === "[object Function]";
};
//Проверка объекта на наличие списка функций
const haveFunctions = (obj, list) => {
//Объявим результат
let res = true;
//Если есть что проверять
if (obj && list) {
//И если пришел массив наименований функций
if (Array.isArray(list)) {
list.forEach(fn => {
if (!isFunction(obj[fn])) res = false;
});
} else {
res = false;
}
} else {
res = false;
}
//Вернем результат
return res;
};
//Проверка корректности интерфейса модуля
const checkModuleInterface = (module, interface) => {
//Объявим результат
let res = true;
//Если есть что проверять
if (module && interface) {
//Eсли есть список функций
if (interface.functions) {
//Проверим их наличие
res = haveFunctions(module, interface.functions);
} else {
res = false;
}
} else {
res = false;
}
//Вернем результат
return res;
};
//Формирование полного пути к подключаемому модулю
const makeModuleFullPath = moduleName => {
if (moduleName) {
return MODULES_PATH_EX + "/" + moduleName;
} else {
return "";
}
};
//-----------------
// Интерфейс модуля
//-----------------
exports.isFunction = isFunction;
exports.haveFunctions = haveFunctions;
exports.checkModuleInterface = checkModuleInterface;
exports.makeModuleFullPath = makeModuleFullPath;

124
index.js
View File

@ -1,62 +1,78 @@
var oracledb = require("oracledb");
var dbConfig = require("./config.js");
/*
Сервис интеграции ПП Парус 8 с WEB API
Точка входа в сервер приложений
*/
require("module-alias/register");
const cfg = require("./config.js");
const { Logger } = require("@core/logger.js");
const db = require("@core/db_connector.js");
const { ServerError } = require("@core/server_errors.js");
const parus = require("@modules/parus_db.js");
const utls = require("@core/utils.js");
// Get a non-pooled connection
oracledb.getConnection(
{
user: dbConfig.user,
password: dbConfig.password,
connectString: dbConfig.connectString
},
function(err, connection) {
if (err) {
console.error(err.message);
return;
}
connection.execute(
// The statement to execute
"SELECT rn, agnabbr FROM agnlist WHERE rn = :id",
let a = new db.DBConnector(cfg.dbConnect);
a.connect()
.then(res => {
console.log(res);
setTimeout(() => {
a.disconnect()
.then(res => {
console.log("DISCONNECTED");
})
.catch(e => {
console.log(e.code + ": " + e.message);
});
}, 2000);
})
.catch(e => {
console.log(e.code + ": " + e.message);
});
// The "bind value" 180 for the bind variable ":id"
[1431890],
/*
// execute() options argument. Since the query only returns one
// row, we can optimize memory usage by reducing the default
// maxRows value. For the complete list of other options see
// the documentation.
{
maxRows: 1
//, outFormat: oracledb.OBJECT // query result format
//, extendedMetaData: true // get extra metadata
//, fetchArraySize: 100 // internal buffer allocation size for tuning
},
const log = new Logger();
log.error("Это ошибка");
log.warn("Предупреждение это");
log.info("Просто информация");
// The callback function handles the SQL execution results
function(err, result) {
if (err) {
console.error(err.message);
setTimeout(() => {
doRelease(connection);
}, 2000);
return;
}
console.log(result.metaData); // [ { name: 'DEPARTMENT_ID' }, { name: 'DEPARTMENT_NAME' } ]
console.log(result.rows); // [ [ 180, 'Construction' ] ]
setTimeout(() => {
doRelease(connection);
}, 2000);
}
);
}
);
// Note: connections should always be released when not needed
function doRelease(connection) {
connection.close(function(err) {
if (err) {
console.log("Connection closed with erros: " + err.message);
const test = async prms => {
return new Promise((resolve, reject) => {
if (prms == 0) {
reject(new ServerError(1234, "Ошибка!"));
} else {
console.log("Connection closed - no erros");
setTimeout(() => {
resolve(prms + 1);
}, 1000);
}
});
}
};
const callTest = async prms => {
try {
console.log("in async before");
let a = await test(prms);
console.log("in async after " + a);
return a;
} catch (e) {
console.log("in async I'm here: " + e.code + " - " + e.message);
throw e;
}
};
process.on("unhandledRejection", err => {
console.error("PROCESS ERROR: " + err.code + " - " + err.message);
process.exit(0);
});
console.log("BEFORE");
callTest(0)
.then(result => {
console.log("MAIN RESULT: " + result);
})
.catch(err => {
console.error("MAIN ERROR: " + err.code + " - " + err.message);
});
console.log("AFTER");
*/

10
package-lock.json generated
View File

@ -4,6 +4,16 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"lodash": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
},
"module-alias": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.1.0.tgz",
"integrity": "sha1-w21P0V9/nXES9i+gFThee2WihsE="
},
"oracledb": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/oracledb/-/oracledb-2.3.0.tgz",

View File

@ -18,6 +18,12 @@
},
"homepage": "https://github.com/CITKParus/ExchangeService#readme",
"dependencies": {
"lodash": "^4.17.11",
"module-alias": "^2.1.0",
"oracledb": "^2.3.0"
},
"_moduleAliases": {
"@core": "core",
"@modules": "modules"
}
}