From 70efa0250d8ca22ff73679821c7fb69dd1a8ab41 Mon Sep 17 00:00:00 2001 From: Mikhail Chechnev Date: Wed, 7 Nov 2018 21:32:28 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B8=D0=BD=D1=81=D1=82=D0=B5=D1=80?= =?UTF-8?q?=D1=84=D0=B5=D0=B9=D1=81=D0=B0=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB?= =?UTF-8?q?=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20=D1=81=20=D0=91?= =?UTF-8?q?=D0=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/constants.js | 4 ++ core/db_connector.js | 70 +++++++++++++++++++++++-------- core/utils.js | 43 +++++++++++++++++++ index.js | 45 +++++++++++++++----- modules/parus_db.js | 98 +++++++++++++++----------------------------- 5 files changed, 167 insertions(+), 93 deletions(-) diff --git a/core/constants.js b/core/constants.js index 33bac2c..97f3a0e 100644 --- a/core/constants.js +++ b/core/constants.js @@ -15,6 +15,10 @@ 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_OBJECT_BAD_INTERFACE = "ERR_OBJECT_BAD_INTERFACE"; //Ошибочный интерфейс объекта + //Типовые коды ошибок работы с БД exports.ERR_DB_CONNECT = "ERR_DB_CONNECT"; //Ошибка подключения к БД exports.ERR_DB_DISCONNECT = "ERR_DB_DISCONNECT"; //Ошибка отключения от БД +exports.ERR_DB_EXECUTE = "ERR_DB_EXECUTE"; //Ошибка исполнения функции в БД diff --git a/core/db_connector.js b/core/db_connector.js index c33dc81..b3d39f7 100644 --- a/core/db_connector.js +++ b/core/db_connector.js @@ -9,7 +9,7 @@ const _ = require("lodash"); //Работа с массивами и объектами const glConst = require("@core/constants.js"); //Глобальные константы -const { checkModuleInterface, makeModuleFullPath } = require("@core/utils.js"); //Вспомогательные функции +const { checkModuleInterface, makeModuleFullPath, checkObject } = require("@core/utils.js"); //Вспомогательные функции const { ServerError } = require("@core/server_errors.js"); //Типовая ошибка //------------ @@ -19,26 +19,55 @@ 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"] })) { + //Проверяем структуру переданного объекта для подключения + let checkResult = checkObject(dbConnect, { + fields: [ + { name: "user", required: true }, + { name: "password", required: true }, + { name: "connectString", required: true }, + { name: "module", required: false } + ] + }); + //Если структура объекта в норме + if (!checkResult) { + //Проверяем наличие модуля для работы с БД в настройках подключения + if (dbConnect.module) { + //Подключим модуль + this.connector = require(makeModuleFullPath(dbConnect.module)); + //Проверим его интерфейс + if ( + !checkModuleInterface(this.connector, { + functions: [ + "connect", + "disconnect", + "getServices", + "log", + "getQueueOutgoing", + "putQueueIncoming", + "setQueueValue" + ] + }) + ) { + 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_BAD_INTERFACE, - "Модуль " + dbConnect.module + " реализует неверный интерфейс!" + glConst.ERR_MODULES_NO_MODULE_SPECIFIED, + "Не указано имя подключаемого модуля-коннектора!" ); } - //Всё успешно - сохраним настройки подключения - this.connectSettings = {}; - _.extend(this.connectSettings, dbConnect); - //Инициализируем остальные свойства - this.connection = {}; } else { throw new ServerError( - glConst.ERR_MODULES_NO_MODULE_SPECIFIED, - "Не указано имя подключаемого модуля-коннектора!" + glConst.ERR_OBJECT_BAD_INTERFACE, + "Объект имеет недопустимый интерфейс: " + checkResult ); } } @@ -62,7 +91,14 @@ class DBConnector { } } //Исполнить запрос - async execute() {} + async getServices() { + try { + let res = await this.connector.getServices(this.connection); + return res; + } catch (e) { + throw new ServerError(glConst.ERR_DB_EXECUTE, e.message); + } + } } //----------------- diff --git a/core/utils.js b/core/utils.js index ecce4ef..7645d79 100644 --- a/core/utils.js +++ b/core/utils.js @@ -59,6 +59,48 @@ const checkModuleInterface = (module, interface) => { return res; }; +//Проверка корректности полей объекта +const checkObject = (obj, interface) => { + //Объявим результат + let res = ""; + //Если есть что проверять + if (obj && interface) { + //Eсли есть список полей для проверки + if (interface.fields) { + if (Array.isArray(interface.fields)) { + let noFields = []; + let noValues = []; + //Обходим проверяемые поля + interface.fields.forEach(fld => { + //Проверим наличие поля в объекте + if (!(fld.name in obj)) { + //Поля нет + noFields.push(fld.name); + } else { + //Поле есть, проверим наличие значения + if (fld.required && !obj[fld.name]) + //Обязательное поле не содержит значения + noValues.push(fld.name); + } + }); + //Сформируем итоговое сообщение + if (noFields.length > 0) res = "Объект не содержит полей: " + noFields.join(", "); + if (noValues.length > 0) + res += + (res == "" ? "" : "; ") + "Обязательные поля объекта не имеют значений: " + noValues.join(", "); + } else { + res = "Список проверяемых полей объекта не является массивом"; + } + } else { + res = "Не указан список проверяемых полей объекта"; + } + } else { + res = "Не указан проверяемый объект и/или его интерфейс"; + } + //Вернем результат + return res; +}; + //Формирование полного пути к подключаемому модулю const makeModuleFullPath = moduleName => { if (moduleName) { @@ -75,4 +117,5 @@ const makeModuleFullPath = moduleName => { exports.isFunction = isFunction; exports.haveFunctions = haveFunctions; exports.checkModuleInterface = checkModuleInterface; +exports.checkObject = checkObject; exports.makeModuleFullPath = makeModuleFullPath; diff --git a/index.js b/index.js index 1a467f5..5828bed 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,11 @@ Сервис интеграции ПП Парус 8 с WEB API Точка входа в сервер приложений */ + +//---------------------- +// Подключение библиотек +//---------------------- + require("module-alias/register"); const cfg = require("./config.js"); const { Logger } = require("@core/logger.js"); @@ -10,19 +15,39 @@ const { ServerError } = require("@core/server_errors.js"); const parus = require("@modules/parus_db.js"); const utls = require("@core/utils.js"); +//------------ +// Тело модуля +//------------ + 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); + console.log("CONNECTED"); + a.getServices() + .then(res => { + console.log(res); + setTimeout(() => { + a.disconnect() + .then(res => { + console.log("DISCONNECTED"); + }) + .catch(e => { + console.log(e.code + ": " + e.message); + }); + }, 10000); + }) + .catch(e => { + console.log(e.code + ": " + e.message); + setTimeout(() => { + a.disconnect() + .then(res => { + console.log("DISCONNECTED"); + }) + .catch(e => { + console.log(e.code + ": " + e.message); + }); + }, 10000); + }); }) .catch(e => { console.log(e.code + ": " + e.message); diff --git a/modules/parus_db.js b/modules/parus_db.js index e2449a2..3cda739 100644 --- a/modules/parus_db.js +++ b/modules/parus_db.js @@ -45,81 +45,47 @@ const disconnect = connection => { } }); } else { - reject(new Error("No connection specified")); + reject(new Error("Не указано подключение")); } }); }; -//Исполнение запроса -const execute = prms => { - console.log("EXECUTE"); +//Получение списка сервисов +const getServices = connection => { + return new Promise((resolve, reject) => { + if (connection) { + connection.execute("select * from EXSSERVICE", [], { outFormat: oracledb.OBJECT }, (err, result) => { + if (err) { + reject(err); + } + resolve(result.rows); + }); + } else { + reject(new Error("Не указано подключение")); + } + }); }; +//Запись в протокол работы +const log = prms => {}; + +//Считывание очередной порции исходящих сообщений из очереди +const getQueueOutgoing = prms => {}; + +//Помещение очередного входящего сообщения в очередь +const putQueueIncoming = prms => {}; + +//Установка значения в сообщении очереди +const setQueueValue = prms => {}; + //----------------- // Интерфейс модуля //----------------- exports.connect = connect; exports.disconnect = disconnect; -exports.execute = execute; - -/* -oracledb.getConnection( - { - user: cfg.dbConnect.user, - password: cfg.dbConnect.password, - connectString: cfg.dbConnect.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", - - // 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 - }, - - // 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); - } else { - console.log("Connection closed - no erros"); - } - }); -} -*/ +exports.getServices = getServices; +exports.log = log; +exports.getQueueOutgoing = getQueueOutgoing; +exports.putQueueIncoming = putQueueIncoming; +exports.setQueueValue = setQueueValue;