Переход к реальной схеме аутентификации (транш второй)

This commit is contained in:
Mikhail Chechnev 2019-01-06 00:36:40 +03:00
parent 01a3e88e6b
commit 1a64f7999b
13 changed files with 488 additions and 198 deletions

View File

@ -14,7 +14,7 @@ let dbConnect = {
//Пароль пользователя БД
sPassword: "parus",
//Строка подключения к БД
sConnectString: "DEMOP_CITKSERV",
sConnectString: "DEMOP_CITKSERV_WAN",
//Наименование сервера приложений в сессии БД
sSessionAppName: "PARUS$ExchangeServer",
//Подключаемый модуль обслуживания БД (низкоуровневые функции работы с СУБД)
@ -24,7 +24,7 @@ let dbConnect = {
//Параметры обработки очереди исходящих сообщений
let outGoing = {
//Количество одновременно обрабатываемых исходящих сообщений
nMaxWorkers: 1,
nMaxWorkers: 3,
//Интервал проверки наличия исходящих сообщений (мс)
nCheckTimeout: 1
};

View File

@ -33,6 +33,7 @@ exports.SERR_MAIL_FAILED = "ERR_MAIL_FAILED"; //Ошибка отправки п
//Типовые коды ошибок WEB-сервера
exports.SERR_WEB_SERVER = "ERR_WEB_SERVER"; //Ошибка WEB-сервера
//Типовые коди ошибок пользовательских обработчиков сервера приложений
//Типовые коди ошибок пользовательских обработчиков сервера приложений и сервера БД
exports.SERR_APP_SERVER_BEFORE = "ERR_APP_SERVER_BEFORE"; //Ошибка предобработчика
exports.SERR_APP_SERVER_AFTER = "ERR_APP_SERVER_AFTER"; //Ошибка постобработчика
exports.SERR_DB_SERVER = "SERR_DB_SERVER"; //Ошибка обработчика сервера БД

View File

@ -139,7 +139,6 @@ class DBConnector extends EventEmitter {
let srvs = await this.connector.getServices({ connection: this.connection });
srvs.forEach(s => {
s.functions = [];
s.context = {};
});
//Валидируем его
let sCheckResult = validateObject({ services: srvs }, objServicesSchema.Services, "Список сервисов");
@ -760,14 +759,19 @@ class DBConnector extends EventEmitter {
if (!sCheckResult) {
//Исполняем действие в БД
try {
let res = await this.connector.execQueuePrc({
nQueueId: prms.nQueueId,
connection: this.connection
});
//Подготовим параметры для передачи в БД
let execQueuePrcData = _.cloneDeep(prms);
execQueuePrcData.connection = this.connection;
//И выполним обработчик со стороны БД
let res = await this.connector.execQueuePrc(execQueuePrcData);
//Валидируем полученный ответ
sCheckResult = validateObject(res, objQueueSchema.Queue, "Изменённое сообщение очереди обмена");
sCheckResult = validateObject(
res,
objQueueSchema.QueuePrcResult,
"Результат обработки очереди обмена"
);
if (sCheckResult) throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
//Вернём измененную запись
//Вернём результат обработки
return res;
} catch (e) {
if (e instanceof ServerError) throw e;

View File

@ -23,7 +23,9 @@ const {
SERR_OBJECT_BAD_INTERFACE,
SERR_WEB_SERVER,
SERR_APP_SERVER_BEFORE,
SERR_APP_SERVER_AFTER
SERR_APP_SERVER_AFTER,
SERR_DB_SERVER,
SERR_UNAUTH
} = require("./constants"); //Общесистемные константы
//--------------------------
@ -144,7 +146,7 @@ class InQueue extends EventEmitter {
nQueueId: q.nId,
nExecState: objQueueSchema.NQUEUE_EXEC_STATE_APP_OK
});
//Фиксируем успех исполнения
//Фиксируем результат исполнения
if (!_.isUndefined(resBefore.blMsg)) {
blMsg = resBefore.blMsg;
q = await this.dbConn.setQueueMsg({
@ -159,6 +161,10 @@ class InQueue extends EventEmitter {
blResp
});
}
//Если пришел флаг ошибочной аутентификации и он положительный - то это ошибка, дальше ничего не делаем
if (!_.isUndefined(resBefore.bUnAuth))
if (resBefore.bUnAuth === true)
throw new ServerError(SERR_UNAUTH, "Не аутентифицирован");
} else {
//Или расскажем об ошибке
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
@ -173,7 +179,13 @@ class InQueue extends EventEmitter {
nExecState: objQueueSchema.NQUEUE_EXEC_STATE_DB
});
//Вызов обработчика БД
q = await this.dbConn.execQueueDBPrc({ nQueueId: q.nId });
let prcRes = await this.dbConn.execQueueDBPrc({ nQueueId: q.nId });
//Если результат - ошибка пробрасываем её
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_ERR)
throw new ServerError(SERR_DB_SERVER, prcRes.sMsg);
//Если результат - ошибка аутентификации, то и её пробрасываем, но с правильным кодом
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_UNAUTH)
throw new ServerError(SERR_UNAUTH, prcRes.sMsg || "Не аутентифицирован");
//Выставим статус сообщению очереди - исполнено обработчиком БД
q = await this.dbConn.setQueueState({
nQueueId: q.nId,
@ -216,7 +228,7 @@ class InQueue extends EventEmitter {
nQueueId: q.nId,
nExecState: objQueueSchema.NQUEUE_EXEC_STATE_APP_OK
});
//Фиксируем успех исполнения
//Фиксируем результат исполнения
if (!_.isUndefined(resAfter.blResp)) {
blResp = resAfter.blResp;
q = await this.dbConn.setQueueResp({
@ -224,6 +236,10 @@ class InQueue extends EventEmitter {
blResp
});
}
//Если пришел флаг ошибочной аутентификации и он положительный - то это ошибка, дальше ничего не делаем
if (!_.isUndefined(resAfter.bUnAuth))
if (resAfter.bUnAuth === true)
throw new ServerError(SERR_UNAUTH, "Не аутентифицирован");
} else {
//Или расскажем об ошибке
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);

View File

@ -220,9 +220,8 @@ class OutQueue extends EventEmitter {
} else {
//Ошибки обработки нет, но может быть есть ошибка аутентификации
if (result.sResult == objOutQueueProcessorSchema.STASK_RESULT_UNAUTH) {
//!!!!!!!!!!!!!!
//??????????????
//!!!!!!!!!!!!!!
//Ставим задачу на аутентификацию сервиса
await this.dbConn.putServiceAuthInQueue({ nServiceId: prms.queue.nServiceId });
}
}
} else {

View File

@ -23,6 +23,7 @@ const {
SERR_OBJECT_BAD_INTERFACE,
SERR_APP_SERVER_BEFORE,
SERR_APP_SERVER_AFTER,
SERR_DB_SERVER,
SERR_UNAUTH
} = require("./constants"); //Глобальные константы
const { NINC_EXEC_CNT_YES, NINC_EXEC_CNT_NO } = require("../models/prms_db_connector"); //Схемы валидации параметров функций модуля взаимодействия с БД
@ -114,21 +115,23 @@ const appProcess = async prms => {
let qData = await dbConn.getQueueMsg({ nQueueId: prms.queue.nId });
//Считаем контекст сервиса
let serviceCtx = await dbConn.getServiceContext({ nServiceId: prms.service.nId });
//Флаг установленности контекста для функции начала сеанса
let bCtxIsSet = false;
//Кладём данные тела в объект сообщения и инициализируем поле для ответа
_.extend(prms.queue, { blMsg: qData.blMsg, blResp: null });
//Кладём данные контекста в сервис
_.extend(prms.service, serviceCtx);
//Собираем параметры для передачи серверу
let options = { method: prms.service.sFnPrmsType };
let options = { method: prms.function.sFnPrmsType };
//Определимся с URL и телом сообщения в зависимости от способа передачи параметров
if (prms.service.sFnPrmsType == objServiceFnSchema.NFN_PRMS_TYPE_POST) {
if (prms.function.nFnPrmsType == objServiceFnSchema.NFN_PRMS_TYPE_POST) {
options.url = buildURL({ sSrvRoot: prms.service.sSrvRoot, sFnURL: prms.function.sFnURL });
options.body = prms.queue.blMsg;
} else {
options.url = buildURL({
sSrvRoot: prms.service.sSrvRoot,
sFnURL: prms.function.sFnURL,
sQuery: prms.queue.blMsg.toString()
sQuery: prms.queue.blMsg === null ? "" : prms.queue.blMsg.toString()
});
}
//Выполняем обработчик "До" (если он есть)
@ -150,26 +153,40 @@ const appProcess = async prms => {
);
//Если структура ответа в норме
if (!sCheckResult) {
//Применим её
//Применим ответ "До" - обработанное сообщение очереди
if (!_.isUndefined(resBefore.blMsg)) {
prms.queue.blMsg = resBefore.blMsg;
await dbConn.setQueueMsg({
nQueueId: prms.queue.nId,
blMsg: prms.queue.blMsg
});
if (prms.service.sFnPrmsType == objServiceFnSchema.NFN_PRMS_TYPE_POST) {
if (prms.function.nFnPrmsType == objServiceFnSchema.NFN_PRMS_TYPE_POST) {
options.body = prms.queue.blMsg;
} else {
options.url = buildURL({
sSrvRoot: prms.service.sSrvRoot,
sFnURL: prms.function.sFnURL,
sQuery: prms.queue.blMsg.toString()
sQuery: prms.queue.blMsg === null ? "" : prms.queue.blMsg.toString()
});
}
}
if (!_.isUndefined(resBefore.options)) options = _.cloneDeep(resBefore.options);
//Применим ответ "До" - параметры отправки сообщения удаленному серверу
if (!_.isUndefined(resBefore.options)) _.extend(options, resBefore.options);
//Применим ответ "До" - флаг отсуствия аутентификации
if (!_.isUndefined(resBefore.bUnAuth))
throw new ServerError(SERR_UNAUTH, "Не аутентифицирован");
if (resBefore.bUnAuth === true) {
throw new ServerError(SERR_UNAUTH, "Не аутентифицирован");
}
//Применим ответ "До" - контекст работы сервиса
if (!_.isUndefined(resBefore.sCtx))
if (prms.function.nFnType == objServiceFnSchema.NFN_TYPE_LOGIN) {
await dbConn.setServiceContext({
nServiceId: prms.service.nId,
sCtx: resBefore.sCtx,
dCtxExp: resBefore.dCtxExp
});
bCtxIsSet = true;
}
} else {
//Или расскажем об ошибке в структуре ответа
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
@ -207,7 +224,7 @@ const appProcess = async prms => {
);
//Если структура ответа в норме
if (!sCheckResult) {
//Применим её
//Применим ответ "После" - обработанный ответ удаленного сервиса
if (!_.isUndefined(resAfter.blResp)) {
prms.queue.blResp = resAfter.blResp;
await dbConn.setQueueResp({
@ -215,14 +232,38 @@ const appProcess = async prms => {
blResp: prms.queue.blResp
});
}
//Применим ответ "После" - флаг утентификации сервиса
if (!_.isUndefined(resAfter.bUnAuth))
throw new ServerError(SERR_UNAUTH, "Не аутентифицирован");
if (resAfter.bUnAuth === true)
throw new ServerError(SERR_UNAUTH, "Не аутентифицирован");
//Применим ответ "После" - контекст работы сервиса
if (!_.isUndefined(resAfter.sCtx))
if (prms.function.nFnType == objServiceFnSchema.NFN_TYPE_LOGIN) {
await dbConn.setServiceContext({
nServiceId: prms.service.nId,
sCtx: resAfter.sCtx,
dCtxExp: resAfter.dCtxExp
});
bCtxIsSet = true;
}
} else {
//Или расскажем об ошибке в структуре ответа
throw new ServerError(SERR_OBJECT_BAD_INTERFACE, sCheckResult);
}
}
}
//Если это функция начала сеанса, и нет обработчика на стороне БД и контекст не был установлен до сих пор - то положим в него то, что нам ответил сервер
if (
prms.function.nFnType == objServiceFnSchema.NFN_TYPE_LOGIN &&
!prms.function.sPrcResp &&
!bCtxIsSet
) {
await dbConn.setServiceContext({ nServiceId: prms.service.nId, sCtx: serverResp });
}
//Если это функция окончания сеанса, и нет обработчика на стороне БД - то сбросим контекст здесь
if (prms.function.nFnType == objServiceFnSchema.NFN_TYPE_LOGOUT && !prms.function.sPrcResp) {
await dbConn.clearServiceContext({ nServiceId: prms.service.nId });
}
//Фиксируем успешное исполнение сервером приложений - в статусе сообщения
res = await dbConn.setQueueState({
nQueueId: prms.queue.nId,
@ -287,8 +328,17 @@ const dbProcess = async prms => {
}, ${prms.queue.sExecState}, попытка исполнения - ${prms.queue.nExecCnt + 1}`,
{ nQueueId: prms.queue.nId }
);
//Вызов обработчика БД
res = await dbConn.execQueueDBPrc({ nQueueId: prms.queue.nId });
//Если обработчик со стороны БД указан
if (prms.function.sPrcResp) {
//Вызываем его
let prcRes = await dbConn.execQueueDBPrc({ nQueueId: prms.queue.nId });
//Если результат - ошибка пробрасываем её
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_ERR)
throw new ServerError(SERR_DB_SERVER, prcRes.sMsg);
//Если результат - ошибка аутентификации, то и её пробрасываем, но с правильным кодом
if (prcRes.sResult == objQueueSchema.SPRC_RESP_RESULT_UNAUTH)
throw new ServerError(SERR_UNAUTH, prcRes.sMsg || "Не аутентифицирован");
}
//Фиксируем успешное исполнение (полное - дальше обработки нет) - в статусе сообщения
res = await dbConn.setQueueState({
nQueueId: prms.queue.nId,
@ -351,8 +401,6 @@ const processTask = async prms => {
await dbConn.connect();
//Считываем запись очереди
q = await dbConn.getQueue({ nQueueId: prms.task.nQueueId });
//Выставим флаг - нет ошибок аутентификации на удаленном сервере
let bUnAuthFlag = false;
//Далее работаем от статуса считанной записи
switch (q.nExecState) {
//Статусы "Поставлено в очередь" или "Ошибка обработки сервером приложений"
@ -361,60 +409,21 @@ const processTask = async prms => {
//Если ещё не обрабатывали или есть ещё попытки отработки
if (q.nExecCnt == 0 || q.nExecCnt < q.nRetryAttempts) {
//Запускаем обработку сервером приложений
try {
let res = await appProcess({
queue: q,
service: prms.task.service,
function: prms.task.function
});
//Если результат обработки - ошибка аутентификации
if (res === objOutQueueProcessorSchema.STASK_RESULT_UNAUTH) {
//Выставим флаг, который будет указывать на ошибку аутентификации
bUnAuthFlag = true;
} else {
//Нет такой ошибки, посмотрим что прилетело сообщение в успешном статусе и тогда запустим обработку сервером БД
if (res.nExecState == objQueueSchema.NQUEUE_EXEC_STATE_APP_OK) {
try {
await dbProcess({ queue: res });
} catch (e) {
//Фиксируем ошибку обработки сервером БД - в статусе сообщения
await dbConn.setQueueState({
nQueueId: res.nId,
sExecMsg: makeErrorText(e),
nIncExecCnt: NINC_EXEC_CNT_YES,
nExecState:
res.nExecCnt + 1 < res.nRetryAttempts
? objQueueSchema.NQUEUE_EXEC_STATE_DB_ERR
: objQueueSchema.NQUEUE_EXEC_STATE_ERR
});
//Фиксируем ошибку обработки сервером БД - в протоколе работы сервиса
await logger.error(
`Ошибка обработки исходящего сообщения ${
res.nId
} сервером БД: ${makeErrorText(e)}`,
{ nQueueId: res.nId }
);
}
}
let res = await appProcess({
queue: q,
service: prms.task.service,
function: prms.task.function
});
//Если результат обработки ошибка - пробрасываем её дальше
if (res instanceof ServerError) {
throw res;
} else {
//Нет ошибки, посмотрим что прилетело сообщение в успешном статусе и тогда запустим обработку сервером БД
if (res.nExecState == objQueueSchema.NQUEUE_EXEC_STATE_APP_OK) {
res = await dbProcess({ queue: res, function: prms.task.function });
//Если результат обработки ошибка - пробрасываем её дальше
if (res instanceof ServerError) throw res;
}
} catch (e) {
//Фиксируем ошибку обработки сервером приложений - в статусе сообщения
newQueue = await dbConn.setQueueState({
nQueueId: q.nId,
sExecMsg: makeErrorText(e),
nIncExecCnt: NINC_EXEC_CNT_YES,
nExecState:
q.nExecCnt + 1 < q.nRetryAttempts
? objQueueSchema.NQUEUE_EXEC_STATE_APP_ERR
: objQueueSchema.NQUEUE_EXEC_STATE_ERR
});
//Фиксируем ошибку обработки сервером приложений - в протоколе работы сервиса
await logger.error(
`Ошибка обработки исходящего сообщения ${q.nId} сервером приложений: ${makeErrorText(
e
)}`,
{ nQueueId: q.nId }
);
}
} else {
//Попыток нет - финализируем обработку
@ -433,25 +442,9 @@ const processTask = async prms => {
//Если ещё есть попытки отработки
if (q.nExecCnt == 0 || q.nExecCnt < q.nRetryAttempts) {
//Снова запускаем обработку сервером БД
try {
await dbProcess({ queue: q });
} catch (e) {
//Фиксируем ошибку обработки сервером БД - в статусе сообщения
await dbConn.setQueueState({
nQueueId: q.nId,
sExecMsg: makeErrorText(e),
nIncExecCnt: NINC_EXEC_CNT_YES,
nExecState:
q.nExecCnt + 1 < q.nRetryAttempts
? objQueueSchema.NQUEUE_EXEC_STATE_DB_ERR
: objQueueSchema.NQUEUE_EXEC_STATE_ERR
});
//Фиксируем ошибку обработки сервером БД - в протоколе работы сервиса
await logger.error(
`Ошибка обработки исходящего сообщения ${q.nId} сервером БД: ${makeErrorText(e)}`,
{ nQueueId: q.nId }
);
}
let res = await dbProcess({ queue: q, function: prms.task.function });
//Если результат обработки ошибка - пробрасываем её дальше
if (res instanceof ServerError) throw res;
} else {
//Попыток нет - финализируем обработку
await dbConn.setQueueState({
@ -493,14 +486,14 @@ const processTask = async prms => {
}
//Отключаемся от БД
if (dbConn) await dbConn.disconnect();
//Отправляем успех или ошибку аутентификации
if (bUnAuthFlag) sendUnAuthResult();
else sendOKResult();
//Отправляем успех
sendOKResult();
} catch (e) {
//Отключаемся от БД
if (dbConn) await dbConn.disconnect();
//Отправляем ошибку
sendErrorResult({ sMessage: makeErrorText(e) });
if (e instanceof ServerError && e.sCode == SERR_UNAUTH) sendUnAuthResult();
else sendErrorResult({ sMessage: makeErrorText(e) });
}
} else {
sendErrorResult({ sMessage: sCheckResult });

View File

@ -9,8 +9,11 @@ create or replace package PKG_EXS as
SCONT_PRC constant PKG_STD.TSTRING := 'PRC'; -- Íàèìåíîâàíèå êîíòåéíåðà äëÿ ïàðàìåòðîâ ïðîöåññà
/* Êîíñòàíòû - ïîëÿ êîíòåéíåðîâ */
SCONT_FLD_SERR constant PKG_STD.TSTRING := 'SERR'; -- Íàèìåíîâàíèå ïîëÿ êîíòåéíåðà äëÿ îøèáêè
SCONT_FLD_BRESP constant PKG_STD.TSTRING := 'BRESP'; -- Íàèìåíîâàíèå ïîëÿ êîíòåéíåðà äëÿ ðåçóëüòàòà îáðàáîòêè
SCONT_FLD_SRESULT constant PKG_STD.TSTRING := 'SRESULT'; -- Íàèìåíîâàíèå ïîëÿ êîíòåéíåðà äëÿ êîäà ðåçóëüòàòà îáðàáîòêè
SCONT_FLD_SMSG constant PKG_STD.TSTRING := 'SMSG'; -- Íàèìåíîâàíèå ïîëÿ êîíòåéíåðà äëÿ ñîîáùåíèÿ îáðàáîòêè
SCONT_FLD_BRESP constant PKG_STD.TSTRING := 'BRESP'; -- Íàèìåíîâàíèå ïîëÿ êîíòåéíåðà äëÿ ðåçóëüòàòà îáðàáîòêè
SCONT_FLD_DCTX_EXP constant PKG_STD.TSTRING := 'DCTX_EXP'; -- Íàèìåíîâàíèå ïîëÿ êîíòåéíåðà äëÿ äàòû èñòå÷åíèÿ êîíòåêòñà ñåðâèñà
SCONT_FLD_SCTX constant PKG_STD.TSTRING := 'SCTX'; -- Íàèìåíîâàíèå ïîëÿ êîíòåéíåðà äëÿ äëÿ êîíòåêñòà ñåðâèñà
/* Êîíñòàíòû - òèïû ñåðâèñîâ */
NSRV_TYPE_SEND constant EXSSERVICE.SRV_TYPE%type := 0; -- Îòïðàâêà ñîîáùåíèé
@ -108,8 +111,13 @@ create or replace package PKG_EXS as
SAUTH_ONLY_YES constant varchar2(40) := 'AUTH_ONLY_YES'; -- Òðåáóåòñÿ àóòåíòèôèêàöèÿ (ñòðîêîâûé êîä)
SAUTH_ONLY_NO constant varchar2(40) := 'AUTH_ONLY_NO'; -- Àóòåíòèôèêàöèÿ íå òðåáóåòñÿ (ñòðîêîâûé êîä)
/* Êîíñòàíòû - êîäû ðåçóëüòàòîâ èñïîëíåíèÿ îáðàáîò÷èêà ñîîáùåíèÿ */
SPRC_RESP_RESULT_OK constant varchar2(40) := 'OK'; -- Îáðàáîòàíî óñïåøíî
SPRC_RESP_RESULT_ERR constant varchar2(40) := 'ERR'; -- Îøèáêà îáðàáîòêè
SPRC_RESP_RESULT_UNAUTH constant varchar2(40) := 'UNAUTH'; -- Íåàóòåíòèôèöèðîâàí
/* Êîíñòàíòû - îæèäàåìûé èíòåðôåéñ ïðîöåäóðû îáðàáîòêè ñîîáùåíèÿ î÷åðåäè íà ñòîðîíå ÁÄ */
SPRC_RESP_ARGS constant varchar2(80) := 'NIDENT,IN,NUMBER;NSRV_TYPE,IN,NUMBER;NEXSQUEUE,IN,NUMBER;'; -- Ñïèñîê ïàðàìåòðîâ ïðîöåäóðû îáðàáîòêè
SPRC_RESP_ARGS constant varchar2(80) := 'NIDENT,IN,NUMBER;NEXSQUEUE,IN,NUMBER;'; -- Ñïèñîê ïàðàìåòðîâ ïðîöåäóðû îáðàáîòêè
/* Ïðîâåðêà àêòèâíîñòè ñåðâåðà ïðèëîæåíèé */
function UTL_APPSRV_IS_ACTIVE
@ -223,6 +231,28 @@ create or replace package PKG_EXS as
SARG in varchar2 -- Íàèìåíîâàíèå ïàðàìåòðà
) return blob; -- Çíà÷åíèå ïàðàìåòðà
/* Óñòàíîâêà ðåçóëüòàòà èñïîëíåíèÿ îáðàáîò÷èêà */
procedure PRC_RESP_RESULT_SET
(
NIDENT in number, -- Èäåíòèôèêàòîð ïðîöåññà
SRESULT in varchar2 := SPRC_RESP_RESULT_OK, -- Êîä ðåçóëüòàòà (ñì. êîíñòàíòû SPRC_RESP_RESULT_*)
BRESP in blob := null, -- Ðåçóëüòàò îáðàáîòêè
SMSG in varchar2 := null, -- Ñîîáùåíèå îáðàáîò÷èêà
SCTX in varchar2 := null, -- Êîíòåêñò
DCTX_EXP in date := null -- Äàòà èñòå÷åíèÿ êîíòåêñòà
);
/* Ñ÷èòûâàíèå ðåçóëüòàòà èñïîëíåíèÿ îáðàáîò÷èêà */
procedure PRC_RESP_RESULT_GET
(
NIDENT in number, -- Èäåíòèôèêàòîð ïðîöåññà
SRESULT out varchar2, -- Êîä ðåçóëüòàòà (ñì. êîíñòàíòû SPRC_RESP_RESULT_*)
BRESP out blob, -- Ðåçóëüòàò îáðàáîòêè
SMSG out varchar2, -- Ñîîáùåíèå îáðàáîò÷èêà
SCTX out varchar2, -- Êîíòåêñò
DCTX_EXP out date -- Äàòà èñòå÷åíèÿ êîíòåêñòà
);
/* Áàçîâîå äîáàâëåíèå â áóôåð îòáîðà äîêóìåíòîâ */
procedure RNLIST_BASE_INSERT
(
@ -269,9 +299,9 @@ create or replace package PKG_EXS as
/* Óñòàíîâêà êîíòåêñòà ñåðâèñà */
procedure SERVICE_CTX_SET
(
NEXSSERVICE in number, -- Ðåã. íîìåð çàïèñè ñåðâèñà
SCTX in varchar2, -- Êîíòåêñò
DCTX_EXP in date -- Äàòà èñòå÷åíèÿ êîíòåêñòà
NEXSSERVICE in number, -- Ðåã. íîìåð çàïèñè ñåðâèñà
SCTX in varchar2, -- Êîíòåêñò
DCTX_EXP in date := null -- Äàòà èñòå÷åíèÿ êîíòåêñòà
);
/* Î÷èñòêà êîíòåêñòà ñåðâèñà */
@ -421,6 +451,13 @@ create or replace package PKG_EXS as
/* Óñòàíîâêà ðåçóëüòàòà îáðàáîòêè çàïèñè î÷åðåäè */
procedure QUEUE_RESP_SET
(
NEXSQUEUE in number, -- Ðåã. íîìåð çàïèñè î÷åðåäè
BRESP in blob -- Ðåçóëüòàò îáðàáîòêè
);
/* Óñòàíîâêà ðåçóëüòàòà îáðàáîòêè çàïèñè î÷åðåäè (âîçâðàùàåò èçìåíåííóþ ïîçèöèþ î÷åðåäè) */
procedure QUEUE_RESP_SET
(
NEXSQUEUE in number, -- Ðåã. íîìåð çàïèñè î÷åðåäè
BRESP in blob, -- Ðåçóëüòàò îáðàáîòêè
@ -436,6 +473,13 @@ create or replace package PKG_EXS as
/* Óñòàíîâêà ñîîáùåíèÿ çàïèñè î÷åðåäè */
procedure QUEUE_MSG_SET
(
NEXSQUEUE in number, -- Ðåã. íîìåð çàïèñè î÷åðåäè
BMSG in blob -- Ðåçóëüòàò îáðàáîòêè
);
/* Óñòàíîâêà ñîîáùåíèÿ çàïèñè î÷åðåäè (âîçâðàùàåò èçìåíåííóþ ïîçèöèþ î÷åðåäè) */
procedure QUEUE_MSG_SET
(
NEXSQUEUE in number, -- Ðåã. íîìåð çàïèñè î÷åðåäè
BMSG in blob, -- Ðåçóëüòàò îáðàáîòêè
@ -500,7 +544,7 @@ create or replace package PKG_EXS as
procedure QUEUE_PRC
(
NEXSQUEUE in number, -- Ðåã. íîìåð çàïèñè î÷åðåäè
RCQUEUE out sys_refcursor -- Êóðñîð ñ îáðàáîòàííîé ïîçèöèåé î÷åðåäè
RCRESULT out sys_refcursor -- Êóðñîð ñ ðåçóëüòàòàìè îáðàáîòêè
);
end;
@ -720,6 +764,10 @@ create or replace package body PKG_EXS as
NARGS_LIST_CUR_CORRECT := 0;
end if;
end loop;
/* Ïðîâåðèì ñîâïàäåíèå è ïî êîëè÷åñòâó */
if (RARGS_LIST.COUNT <> RARGS_LIST_CUR.COUNT) then
NARGS_LIST_CUR_CORRECT := 0;
end if;
/* Óñòàíîâêà ðåçóëüòàòà */
NRESULT := NARGS_LIST_CUR_CORRECT;
/* Óñòàíîâèì ñîîáùåíèå îá îæèäàåìîì èíòåðôåéñå */
@ -1006,24 +1054,88 @@ create or replace package body PKG_EXS as
SCONTAINER := UTL_CONTAINER_MAKE_NAME(NIDENT => NIDENT);
/* Ñ÷èòàåì çíà÷åíèå èäåíòèôèêàòîðà áóôåðà èç êîíòåéíåðà */
NFILE_IDENT := PKG_CONTVARGLB.GETN(SCONTAINER => SCONTAINER, SNAME => SARG);
/* Çàáåðåì ðåçóëüòàòû îáðàáîòêè èç ôàéëîâîãî áóôåðà */
begin
select T.BDATA into BRESP from FILE_BUFFER T where T.IDENT = NFILE_IDENT;
exception
when NO_DATA_FOUND then
P_EXCEPTION(0,
'Ðåçóëüòàòû îáðàáîòêè íå íàéäåíû â áóôåðå (IDENT: %s).',
TO_CHAR(NFILE_IDENT));
when TOO_MANY_ROWS then
P_EXCEPTION(0,
'Ðåçóëüòàòû îáðàáîòêè íå îïðåäåëåíû îäíîçíà÷íî (IDENT: %s).',
TO_CHAR(NFILE_IDENT));
end;
/* Çà÷èñòèì ôàéëîâûé áóôåð */
P_FILE_BUFFER_CLEAR(NIDENT => NFILE_IDENT);
/* Åñëè èäåíòèôèêàòîð áóôåðà áûë â êîíòåéíåðå */
if (NFILE_IDENT is not null) then
/* Çàáåðåì ðåçóëüòàòû îáðàáîòêè èç ôàéëîâîãî áóôåðà */
begin
select T.BDATA into BRESP from FILE_BUFFER T where T.IDENT = NFILE_IDENT;
exception
when NO_DATA_FOUND then
P_EXCEPTION(0,
'Ðåçóëüòàòû îáðàáîòêè íå íàéäåíû â áóôåðå (IDENT: %s).',
TO_CHAR(NFILE_IDENT));
when TOO_MANY_ROWS then
P_EXCEPTION(0,
'Ðåçóëüòàòû îáðàáîòêè íå îïðåäåëåíû îäíîçíà÷íî (IDENT: %s).',
TO_CHAR(NFILE_IDENT));
end;
/* Çà÷èñòèì ôàéëîâûé áóôåð */
P_FILE_BUFFER_CLEAR(NIDENT => NFILE_IDENT);
else
/* Èäåíòèôèêàòîð áóôåðà â êîíòåéíåðå îòñóòñòâîâàë - äàííûõ íåò */
BRESP := null;
end if;
/* Âåðí¸ì çíà÷åíèå */
return BRESP;
end PRC_RESP_ARG_BLOB_GET;
/* Óñòàíîâêà ðåçóëüòàòà èñïîëíåíèÿ îáðàáîò÷èêà */
procedure PRC_RESP_RESULT_SET
(
NIDENT in number, -- Èäåíòèôèêàòîð ïðîöåññà
SRESULT in varchar2 := SPRC_RESP_RESULT_OK, -- Êîä ðåçóëüòàòà (ñì. êîíñòàíòû SPRC_RESP_RESULT_*)
BRESP in blob := null, -- Äàííûå îòâåòà
SMSG in varchar2 := null, -- Ñîîáùåíèå îáðàáîò÷èêà
SCTX in varchar2 := null, -- Êîíòåêñò
DCTX_EXP in date := null -- Äàòà èñòå÷åíèÿ êîíòåêñòà
)
is
begin
/* Ïðîâåðèì ïàðàìåòðû */
if (SRESULT is not null) then
if (SRESULT not in (SPRC_RESP_RESULT_OK, SPRC_RESP_RESULT_ERR, SPRC_RESP_RESULT_UNAUTH)) then
P_EXCEPTION(0,
'Êîä ðåçóëüòàòà èñïîëíåíèÿ îáðàáîò÷èêà "%s" íå ïîääåðæèâàåòñÿ',
SRESULT);
end if;
else
P_EXCEPTION(0, 'Íå óêàçàí êîä ðåçóëüòàòà èñïîëíåíèÿ îáðàáîò÷èêà');
end if;
/* Ñîõðàíÿåì êîä ðåçóëüòàòà */
PRC_RESP_ARG_STR_SET(NIDENT => NIDENT, SARG => SCONT_FLD_SRESULT, SVALUE => SRESULT);
/* Ñîõðàíÿåì äàííûå îòâåòà */
PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, SARG => SCONT_FLD_BRESP, BVALUE => BRESP);
/* Ñîõðàíÿåì ñîîáùåíèå îáðàáîò÷èêà */
PRC_RESP_ARG_STR_SET(NIDENT => NIDENT, SARG => SCONT_FLD_SMSG, SVALUE => SMSG);
/* Ñîõðàíÿåì êîíòåêñò */
PRC_RESP_ARG_STR_SET(NIDENT => NIDENT, SARG => SCONT_FLD_SCTX, SVALUE => SCTX);
/* Ñîõðàíÿåì äàòó èñòå÷åíèÿ êîíòåêñòà */
PRC_RESP_ARG_DATE_SET(NIDENT => NIDENT, SARG => SCONT_FLD_DCTX_EXP, DVALUE => DCTX_EXP);
end PRC_RESP_RESULT_SET;
/* Ñ÷èòûâàíèå ðåçóëüòàòà èñïîëíåíèÿ îáðàáîò÷èêà */
procedure PRC_RESP_RESULT_GET
(
NIDENT in number, -- Èäåíòèôèêàòîð ïðîöåññà
SRESULT out varchar2, -- Êîä ðåçóëüòàòà (ñì. êîíñòàíòû SPRC_RESP_RESULT_*)
BRESP out blob, -- Äàííûå îòâåòà
SMSG out varchar2, -- Ñîîáùåíèå îáðàáîò÷èêà
SCTX out varchar2, -- Êîíòåêñò
DCTX_EXP out date -- Äàòà èñòå÷åíèÿ êîíòåêñòà
)
is
begin
/* Ñ÷èòàåì êîä ðåçóëüòàòà */
SRESULT := PRC_RESP_ARG_STR_GET(NIDENT => NIDENT, SARG => SCONT_FLD_SRESULT);
/* Ñ÷èòàåì äàííûå îòâåòà */
BRESP := PRC_RESP_ARG_BLOB_GET(NIDENT => NIDENT, SARG => SCONT_FLD_BRESP);
/* Ñ÷èòàåì ñîîáùåíèå îáðàáîò÷èêà */
SMSG := PRC_RESP_ARG_STR_GET(NIDENT => NIDENT, SARG => SCONT_FLD_SMSG);
/* Ñ÷èòàåì êîíòåêñò */
SCTX := PRC_RESP_ARG_STR_GET(NIDENT => NIDENT, SARG => SCONT_FLD_SCTX);
/* Ñ÷èòàåì äàòó èñòå÷åíèÿ êîíòåêñòà */
DCTX_EXP := PRC_RESP_ARG_DATE_GET(NIDENT => NIDENT, SARG => SCONT_FLD_DCTX_EXP);
end PRC_RESP_RESULT_GET;
/* Áàçîâîå äîáàâëåíèå â áóôåð îòáîðà äîêóìåíòîâ */
procedure RNLIST_BASE_INSERT
@ -1149,7 +1261,7 @@ create or replace package body PKG_EXS as
(
NEXSSERVICE in number, -- Ðåã. íîìåð çàïèñè ñåðâèñà
SCTX in varchar2, -- Êîíòåêñò
DCTX_EXP in date -- Äàòà èñòå÷åíèÿ êîíòåêñòà
DCTX_EXP in date := null -- Äàòà èñòå÷åíèÿ êîíòåêñòà
)
is
REXSSERVICE EXSSERVICE%rowtype; -- Çàïèñü ñåðâèñà
@ -1386,7 +1498,7 @@ create or replace package body PKG_EXS as
SRETRY_SCHEDULE_MONTH) "sRetrySchedule",
T.EXSMSGTYPE "nMsgId",
M.CODE "sMsgCode",
DECODE(M.PRC_RESP, null, null, UTL_STORED_MAKE_LINK(SPROCEDURE => M.PRC_RESP, SPACKAGE => M.PKG_RESP)) "sPrcResp",
DECODE(M.PRC_RESP, null, null, UTL_STORED_MAKE_LINK(M.PRC_RESP, M.PKG_RESP)) "sPrcResp",
M.APPSRV_BEFORE "sAppSrvBefore",
M.APPSRV_AFTER "sAppSrvAfter",
T.AUTH_ONLY "nAuthOnly",
@ -1833,9 +1945,24 @@ create or replace package body PKG_EXS as
open RCQUEUE_RESP for
select REXSQUEUE.RESP "blResp" from DUAL;
end QUEUE_RESP_GET;
/* Óñòàíîâêà ðåçóëüòàòà îáðàáîòêè çàïèñè î÷åðåäè */
procedure QUEUE_RESP_SET
(
NEXSQUEUE in number, -- Ðåã. íîìåð çàïèñè î÷åðåäè
BRESP in blob -- Ðåçóëüòàò îáðàáîòêè
)
is
begin
/* Âûñòàâèì ðåçóëüòàò */
update EXSQUEUE T set T.RESP = BRESP where T.RN = NEXSQUEUE;
if (sql%rowcount = 0) then
PKG_MSG.RECORD_NOT_FOUND(NFLAG_SMART => 0, NDOCUMENT => NEXSQUEUE, SUNIT_TABLE => 'EXSQUEUE');
end if;
end QUEUE_RESP_SET;
/* Óñòàíîâêà ðåçóëüòàòà îáðàáîòêè çàïèñè î÷åðåäè (âîçâðàùàåò èçìåíåííóþ ïîçèöèþ î÷åðåäè) */
procedure QUEUE_RESP_SET
(
NEXSQUEUE in number, -- Ðåã. íîìåð çàïèñè î÷åðåäè
BRESP in blob, -- Ðåçóëüòàò îáðàáîòêè
@ -1844,10 +1971,7 @@ create or replace package body PKG_EXS as
is
begin
/* Âûñòàâèì ðåçóëüòàò */
update EXSQUEUE T set T.RESP = BRESP where T.RN = NEXSQUEUE;
if (sql%rowcount = 0) then
PKG_MSG.RECORD_NOT_FOUND(NFLAG_SMART => 0, NDOCUMENT => NEXSQUEUE, SUNIT_TABLE => 'EXSQUEUE');
end if;
QUEUE_RESP_SET(NEXSQUEUE => NEXSQUEUE, BRESP => BRESP);
/* Âåðíåì èçìåíåííóþ ïîçèöèþ î÷åðåäè */
QUEUE_GET(NFLAG_SMART => 0, NEXSQUEUE => NEXSQUEUE, RCQUEUE => RCQUEUE);
end QUEUE_RESP_SET;
@ -1867,9 +1991,24 @@ create or replace package body PKG_EXS as
open RCQUEUE_MSG for
select REXSQUEUE.MSG "blMsg" from DUAL;
end QUEUE_MSG_GET;
/* Óñòàíîâêà ñîîáùåíèÿ çàïèñè î÷åðåäè */
procedure QUEUE_MSG_SET
(
NEXSQUEUE in number, -- Ðåã. íîìåð çàïèñè î÷åðåäè
BMSG in blob -- Ðåçóëüòàò îáðàáîòêè
)
is
begin
/* Âûñòàâèì ñîîáùåíèå */
update EXSQUEUE T set T.MSG = BMSG where T.RN = NEXSQUEUE;
if (sql%rowcount = 0) then
PKG_MSG.RECORD_NOT_FOUND(NFLAG_SMART => 0, NDOCUMENT => NEXSQUEUE, SUNIT_TABLE => 'EXSQUEUE');
end if;
end QUEUE_MSG_SET;
/* Óñòàíîâêà ñîîáùåíèÿ çàïèñè î÷åðåäè (âîçâðàùàåò èçìåíåííóþ ïîçèöèþ î÷åðåäè) */
procedure QUEUE_MSG_SET
(
NEXSQUEUE in number, -- Ðåã. íîìåð çàïèñè î÷åðåäè
BMSG in blob, -- Ðåçóëüòàò îáðàáîòêè
@ -1878,10 +2017,7 @@ create or replace package body PKG_EXS as
is
begin
/* Âûñòàâèì ñîîáùåíèå */
update EXSQUEUE T set T.MSG = BMSG where T.RN = NEXSQUEUE;
if (sql%rowcount = 0) then
PKG_MSG.RECORD_NOT_FOUND(NFLAG_SMART => 0, NDOCUMENT => NEXSQUEUE, SUNIT_TABLE => 'EXSQUEUE');
end if;
QUEUE_MSG_SET(NEXSQUEUE => NEXSQUEUE, BMSG => BMSG);
/* Âåðíåì èçìåíåííóþ ïîçèöèþ î÷åðåäè */
QUEUE_GET(NFLAG_SMART => 0, NEXSQUEUE => NEXSQUEUE, RCQUEUE => RCQUEUE);
end QUEUE_MSG_SET;
@ -2036,15 +2172,19 @@ create or replace package body PKG_EXS as
procedure QUEUE_PRC
(
NEXSQUEUE in number, -- Ðåã. íîìåð çàïèñè î÷åðåäè
RCQUEUE out sys_refcursor -- Êóðñîð ñ îáðàáîòàííîé ïîçèöèåé î÷åðåäè
RCRESULT out sys_refcursor -- Êóðñîð ñ ðåçóëüòàòàìè îáðàáîòêè
)
is
REXSQUEUE EXSQUEUE%rowtype; -- Çàïèñü ïîçèöèè î÷åðåäè
REXSSERVICE EXSSERVICE%rowtype; -- Çàïèñü ñåðâèñà îáðàáîòêè
REXSSERVICEFN EXSSERVICEFN%rowtype; -- Çàïèñü ôóíêöèè îáðàáîòêè
REXSMSGTYPE EXSMSGTYPE%rowtype; -- Çàïèñü òèïîâîãî ñîîáùåíèÿ îáìåíà
SERR EXSQUEUE.EXEC_MSG%type; -- Ñîîáùåíèå îá îøèáêå îáðàáîò÷èêà
REXSMSGTYPE EXSMSGTYPE%rowtype; -- Çàïèñü òèïîâîãî ñîîáùåíèÿ îáìåíà
NIDENT PKG_STD.TREF; -- Èäåíòèôèêàòîð ïðîöåññà îáðàáîòêè
SRESULT PKG_STD.TSTRING; -- Áóôåð äëÿ ðåçóëüòàòà: êîä ðåçóëüòàòà
BRESP blob; -- Áóôåð äëÿ ðåçóëüòàòà: äàííûå îòâåòà
SMSG PKG_STD.TSTRING; -- Áóôåð äëÿ ðåçóëüòàòà: ñîîáùåíèå îáðàáîò÷èêà
SCTX PKG_STD.TSTRING; -- Áóôåð äëÿ ðåçóëüòàòà: êîíòåêñò
DCTX_EXP PKG_STD.TLDATE; -- Áóôåð äëÿ ðåçóëüòàòà: äàòà èñòå÷åíèÿ êîíòåêñòà
PRMS PKG_CONTPRMLOC.TCONTAINER; -- Êîíòåéíåð äëÿ ïàðàìåòðîâ ïðîöåäóðû îáðàáîòêè
begin
/* Ñ÷èòàåì çàïèñü î÷åðåäè */
@ -2057,49 +2197,95 @@ create or replace package body PKG_EXS as
REXSMSGTYPE := GET_EXSMSGTYPE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.EXSMSGTYPE);
/* Çàïóñòèì îáðàáîò÷èê, åñëè îí åñòü */
if (REXSMSGTYPE.PRC_RESP is not null) then
/* Ïðîâåðÿåì èíòåðôåéñ îáðàáîò÷èêà */
UTL_STORED_CHECK(NFLAG_SMART => 0,
SPKG => REXSMSGTYPE.PKG_RESP,
SPRC => REXSMSGTYPE.PRC_RESP,
SARGS => SPRC_RESP_ARGS,
NRESULT => NIDENT);
/* Ôîðìèðóåì èäåíòèôèêàòîð ïðîöåññà */
NIDENT := GEN_IDENT();
/* Óñòàíîâèì çíà÷åíèÿ ôèêñèðîâàííûõ âõîäíûõ ïàðàìåòðîâ */
PKG_CONTPRMLOC.APPENDN(RCONTAINER => PRMS,
SNAME => 'NIDENT',
NVALUE => NIDENT,
NIN_OUT => PKG_STD.IPARAM_TYPE_IN);
PKG_CONTPRMLOC.APPENDN(RCONTAINER => PRMS,
SNAME => 'NSRV_TYPE',
NVALUE => REXSSERVICE.SRV_TYPE,
NIN_OUT => PKG_STD.IPARAM_TYPE_IN);
PKG_CONTPRMLOC.APPENDN(RCONTAINER => PRMS,
SNAME => 'NEXSQUEUE',
NVALUE => REXSQUEUE.RN,
NIN_OUT => PKG_STD.IPARAM_TYPE_IN);
/* Èñïîëíÿåì ïðîöåäóðó */
PKG_SQL_CALL.EXECUTE_STORED(SSTORED_NAME => UTL_STORED_MAKE_LINK(SPACKAGE => REXSMSGTYPE.PKG_RESP,
SPROCEDURE => REXSMSGTYPE.PRC_RESP),
RPARAM_CONTAINER => PRMS);
/* Çàáèðàåì ïàðàìåòð ñ îøèáêàìè îáðàáîò÷èêà */
SERR := PRC_RESP_ARG_STR_GET(NIDENT => NIDENT, SARG => SCONT_FLD_SERR);
/* Åñëè áûëè îøèáêè - ñêàæåì îá ýòîì */
if (SERR is not null) then
P_EXCEPTION(0, SERR);
else
/* Çàôèêñèðóåì ðåçóëüòàò îáðàáîòêè (òîëüêî äëÿ âõîäÿùèõ è òîëüêî åñëè íåò îøèáîê îáðàáîòêè) */
if (REXSSERVICE.SRV_TYPE = NSRV_TYPE_RECIVE) then
QUEUE_RESP_SET(NEXSQUEUE => REXSQUEUE.RN,
BRESP => PRC_RESP_ARG_BLOB_GET(NIDENT => NIDENT, SARG => SCONT_FLD_BRESP),
RCQUEUE => RCQUEUE);
begin
/* Ïðîâåðÿåì èíòåðôåéñ îáðàáîò÷èêà */
UTL_STORED_CHECK(NFLAG_SMART => 0,
SPKG => REXSMSGTYPE.PKG_RESP,
SPRC => REXSMSGTYPE.PRC_RESP,
SARGS => SPRC_RESP_ARGS,
NRESULT => NIDENT);
/* Ôîðìèðóåì èäåíòèôèêàòîð ïðîöåññà */
NIDENT := GEN_IDENT();
/* Óñòàíîâèì çíà÷åíèÿ ôèêñèðîâàííûõ âõîäíûõ ïàðàìåòðîâ */
PKG_CONTPRMLOC.APPENDN(RCONTAINER => PRMS,
SNAME => 'NIDENT',
NVALUE => NIDENT,
NIN_OUT => PKG_STD.IPARAM_TYPE_IN);
PKG_CONTPRMLOC.APPENDN(RCONTAINER => PRMS,
SNAME => 'NEXSQUEUE',
NVALUE => REXSQUEUE.RN,
NIN_OUT => PKG_STD.IPARAM_TYPE_IN);
/* Èñïîëíÿåì ïðîöåäóðó */
PKG_SQL_CALL.EXECUTE_STORED(SSTORED_NAME => UTL_STORED_MAKE_LINK(SPACKAGE => REXSMSGTYPE.PKG_RESP,
SPROCEDURE => REXSMSGTYPE.PRC_RESP),
RPARAM_CONTAINER => PRMS);
/* Î÷èñòèì êîíòåéíåð ïàðàìåòðîâ */
PKG_CONTPRMLOC.PURGE(RCONTAINER => PRMS);
/* Çàáèðàåì ðåçóëüòàòû */
PRC_RESP_RESULT_GET(NIDENT => NIDENT,
SRESULT => SRESULT,
BRESP => BRESP,
SMSG => SMSG,
SCTX => SCTX,
DCTX_EXP => DCTX_EXP);
/* Åñëè êîä ðåçóëüòàòà óñòàíîâëåí */
if (SRESULT is not null) then
/* È åñëè ðåçóëüòàò óñïåøåí - ïðèìåíèì åãî */
if (SRESULT = SPRC_RESP_RESULT_OK) then
/* Çàôèêñèðóåì ðåçóëüòàò îáðàáîòêè (äëÿ âõîäÿùèõ - âñåãäà, äëÿ èñõîäÿùèõ - òîëüêî åñëè íå ïóñòîé) */
if ((REXSSERVICE.SRV_TYPE = NSRV_TYPE_RECIVE) or
((REXSSERVICE.SRV_TYPE = NSRV_TYPE_SEND) and (BRESP is not null) and (DBMS_LOB.GETLENGTH(BRESP) > 0))) then
QUEUE_RESP_SET(NEXSQUEUE => REXSQUEUE.RN, BRESP => BRESP);
end if;
/* Åñëè ýòî áûëà ôóíêöèÿ íà÷àëà ñåàíñà */
if (REXSSERVICEFN.FN_TYPE = NFN_TYPE_LOGIN) then
/* Åñëè îáðàáîò÷èê âåðíóë êîíòåêñò */
if (SCTX is not null) then
/* Ïðîïèøåì åãî ñåðâèñó, âíå çàâèñèìîñòè îò òîãî, ÷òî òàì áûëî äî ýòîãî */
SERVICE_CTX_SET(NEXSSERVICE => REXSSERVICE.RN, SCTX => SCTX, DCTX_EXP => DCTX_EXP);
else
/* Îáðàáîò÷èê íå âåðíóë êîíòåêñòà, ïðîâåðèì, åñòü ëè îí ñåé÷àñ ó ñåðâèñà */
REXSSERVICE := GET_EXSSERVICE_ID(NFLAG_SMART => 0, NRN => REXSSERVICEFN.PRN);
if (REXSSERVICE.CTX is null) then
/* Îáðàáîò÷èê íå âåðíóë êîíòåêñò è ñåé÷àñ îí íå óñòàíîâëåí äëÿ ñåðâèñà, ýòî ïðîáëåìà - áîëüøå îáðàáîòîê íå áóäåò çíà÷èò ìû íå çàëîãèíèëèñü */
P_EXCEPTION(0,
'Ôóíêöèÿ íà÷àëà ñåàíñà "%s" íå óñòàíîâèëà êîíòåêñò ðàáîòû äëÿ ñåðâèñà "%s"',
REXSSERVICEFN.CODE,
REXSSERVICE.CODE);
end if;
end if;
end if;
/* Åñëè ýòî áûëà ôóíêöèÿ çàâåðøåíèÿ ñåàíñà */
if (REXSSERVICEFN.FN_TYPE = NFN_TYPE_LOGOUT) then
/* Óäàëèì êîíòåêñò ñåðâèñà */
SERVICE_CTX_CLEAR(NEXSSERVICE => REXSSERVICE.RN);
end if;
else
/* Âî âñåõ îñòàëüíûõ ñëó÷àÿõ - îòêàòûâàåì òðàíçàêöèþ, ò.ê. åñòü êàêèå-òî îøèáêè îáðàáîòêè */
rollback;
end if;
else
/* Ðåçóëüòàò íå óñòàíîâëåí - ýòî îøèáêà */
P_EXCEPTION(0,
'Ïðîöåäóðà îáðàáîò÷èê "%s" íå âåðíóëà ðåçóëüòàò ðàáîòû',
UTL_STORED_MAKE_LINK(SPACKAGE => REXSMSGTYPE.PKG_RESP, SPROCEDURE => REXSMSGTYPE.PRC_RESP));
end if;
end if;
/* Î÷èñòèì êîíòåéíåð ïàðàìåòðîâ */
PKG_CONTPRMLOC.PURGE(RCONTAINER => PRMS);
exception
when others then
rollback;
SRESULT := SPRC_RESP_RESULT_ERR;
SMSG := sqlerrm;
end;
else
/* Îáðàáîò÷èêà íåò è íåò ïðîáëåì */
SRESULT := SPRC_RESP_RESULT_OK;
SMSG := null;
end if;
/* Âîçâðàùàåì îáðàáîòàííóþ ïîçèöèþ î÷åðåäè */
QUEUE_GET(NFLAG_SMART => 0, NEXSQUEUE => REXSQUEUE.RN, RCQUEUE => RCQUEUE);
/* Âîçâðàùàåì ðåçóëüòàò â âèäå êóðñîðà */
open RCRESULT for
select SRESULT "sResult",
SMSG "sMsg"
from DUAL;
end QUEUE_PRC;
end;

View File

@ -33,6 +33,16 @@ exports.InQueueProcessorFnBefore = new Schema({
type: path => `Ответ системы (${path}) имеет некорректный тип данных (ожидалось - Buffer)`,
required: path => `Не указан ответ системы (${path})`
}
},
//Флаг ошибки аутентификации удаленного клиента
bUnAuth: {
type: Boolean,
required: false,
message: {
type: path =>
`Флаг ошибки аутентификации удаленного клиента (${path}) имеет некорректный тип данных (ожидалось - Boolean)`,
required: path => `Не указан флаг ошибки аутентификации удаленного клиента (${path})`
}
}
});
@ -46,5 +56,15 @@ exports.InQueueProcessorFnAfter = new Schema({
type: path => `Обработанный ответ системы (${path}) имеет некорректный тип данных (ожидалось - Buffer)`,
required: path => `Не указан обработанный ответ системы (${path})`
}
},
//Флаг ошибки аутентификации удаленного клиента
bUnAuth: {
type: Boolean,
required: false,
message: {
type: path =>
`Флаг ошибки аутентификации удаленного клиента (${path}) имеет некорректный тип данных (ожидалось - Boolean)`,
required: path => `Не указан флаг ошибки аутентификации удаленного клиента (${path})`
}
}
});

View File

@ -127,6 +127,24 @@ exports.OutQueueProcessorFnBefore = new Schema({
`Флаг ошибки аутентификации на удаленном сервисе (${path}) имеет некорректный тип данных (ожидалось - Boolean)`,
required: path => `Не указан флаг ошибки аутентификации на удаленном сервисе (${path})`
}
},
//Контекст сервиса
sCtx: {
type: String,
required: false,
message: {
type: path => `Контектс сервиса (${path}) имеет некорректный тип данных (ожидалось - String)`,
required: path => `Не указан контекст сервиса (${path})`
}
},
//Дата истечения контекста
dCtxExp: {
type: Date,
required: false,
message: {
type: path => `Дата истечения контекста (${path}) имеет некорректный тип данных (ожидалось - Date)`,
required: path => `Не указана дата истечения контекста (${path})`
}
}
});
@ -151,5 +169,23 @@ exports.OutQueueProcessorFnAfter = new Schema({
`Флаг ошибки аутентификации на удаленном сервисе (${path}) имеет некорректный тип данных (ожидалось - Boolean)`,
required: path => `Не указан флаг ошибки аутентификации на удаленном сервисе (${path})`
}
},
//Контекст сервиса
sCtx: {
type: String,
required: false,
message: {
type: path => `Контектс сервиса (${path}) имеет некорректный тип данных (ожидалось - String)`,
required: path => `Не указан контекст сервиса (${path})`
}
},
//Дата истечения контекста
dCtxExp: {
type: Date,
required: false,
message: {
type: path => `Дата истечения контекста (${path}) имеет некорректный тип данных (ожидалось - Date)`,
required: path => `Не указана дата истечения контекста (${path})`
}
}
});

View File

@ -33,6 +33,11 @@ const SQUEUE_EXEC_STATE_DB_ERR = "DB_ERR"; //Ошибка обработки С
const SQUEUE_EXEC_STATE_OK = "OK"; //Обработано успешно (строковый код)
const SQUEUE_EXEC_STATE_ERR = "ERR"; //Обработано с ошибками (строковый код)
//Коды результатов исполнения обработчика сообщения
const SPRC_RESP_RESULT_OK = "OK"; //Обработано успешно
const SPRC_RESP_RESULT_ERR = "ERR"; //Ошибка обработки
const SPRC_RESP_RESULT_UNAUTH = "UNAUTH"; //Неаутентифицирован
//------------------
// Интерфейс модуля
//------------------
@ -56,6 +61,9 @@ exports.SQUEUE_EXEC_STATE_DB_OK = SQUEUE_EXEC_STATE_DB_OK;
exports.SQUEUE_EXEC_STATE_DB_ERR = SQUEUE_EXEC_STATE_DB_ERR;
exports.SQUEUE_EXEC_STATE_OK = SQUEUE_EXEC_STATE_OK;
exports.SQUEUE_EXEC_STATE_ERR = SQUEUE_EXEC_STATE_ERR;
exports.SPRC_RESP_RESULT_OK = SPRC_RESP_RESULT_OK;
exports.SPRC_RESP_RESULT_ERR = SPRC_RESP_RESULT_ERR;
exports.SPRC_RESP_RESULT_UNAUTH = SPRC_RESP_RESULT_UNAUTH;
//Схема валидации сообщения очереди обмена
exports.Queue = new Schema({
@ -270,3 +278,31 @@ exports.QueueResp = new Schema({
}
}
}).validator({ required: val => val === null || val });
//Схема валидации результата обработки сообщения очереди
exports.QueuePrcResult = new Schema({
//Состояние обработки сообщения очереди обмена
sResult: {
type: String,
enum: [SPRC_RESP_RESULT_OK, SPRC_RESP_RESULT_ERR, SPRC_RESP_RESULT_UNAUTH],
required: true,
message: {
type: path =>
`Состояние обработки сообщения очереди обмена (${path}) имеет некорректный тип данных (ожидалось - String)`,
enum: path => `Значение состояния обработки сообщения очереди обмена (${path}) не поддерживается`,
required: path => `Не указано состояние обработки сообщения очереди обмена (${path})`
}
},
//Информация от обработчика сообщения очереди обмена
sMsg: {
type: String,
required: true,
message: {
type: path =>
`Информация от обработчика сообщения очереди обмена (${path}) имеет некорректный тип данных (ожидалось - String)`,
required: path => `Не указана информация от обработчика сообщения очереди обмена (${path})`
}
}
}).validator({
required: val => typeof val != "undefined"
});

View File

@ -190,16 +190,7 @@ exports.Service = new Schema({
}
},
//Список функций сервиса
functions: defServiceFunctions(true, "functions"),
//Контекст работы сервиса
context: {
type: Object,
required: true,
message: {
type: "Контекст работы сервиса (context) имеет некорректный тип данных (ожидалось - Object)",
required: "Не указан контекст работы сервиса (context)"
}
}
functions: defServiceFunctions(true, "functions")
});
//Схема валидации контекста сервиса

View File

@ -67,6 +67,14 @@ exports.dbProcess = new Schema({
message: {
required: path => `Не указано обрабатываемое сообщение очреди (${path})`
}
},
//Функция сервиса-обработчика
function: {
schema: ServiceFunction,
required: true,
message: {
required: path => `Не указана функция сервиса для обработки сообщения очереди (${path})`
}
}
});

View File

@ -341,14 +341,14 @@ const setQueueResp = async prms => {
const execQueuePrc = async prms => {
try {
let res = await prms.connection.execute(
"BEGIN PKG_EXS.QUEUE_PRC(NEXSQUEUE => :NEXSQUEUE, RCQUEUE => :RCQUEUE); END;",
"BEGIN PKG_EXS.QUEUE_PRC(NEXSQUEUE => :NEXSQUEUE, RCRESULT => :RCRESULT); END;",
{
NEXSQUEUE: prms.nQueueId,
RCQUEUE: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
RCRESULT: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
},
{ outFormat: oracledb.OBJECT, autoCommit: true }
);
let rows = await readCursorData(res.outBinds.RCQUEUE);
let rows = await readCursorData(res.outBinds.RCRESULT);
return rows[0];
} catch (e) {
throw new Error(e.message);