From 99376d2072311c909cc5f798175aae38e2dd0bb6 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 24 May 2021 20:03:16 +0200 Subject: [PATCH] Utilities Error Handling Functions imlpemented --- Projects/ProjectsSchema.json | 6 + .../API-Data-Fetcher-Bot/FetchingProcess.js | 132 +++++++----------- .../TS/Utilities/ErrorHandlingFunctions.js | 51 +++++++ 3 files changed, 110 insertions(+), 79 deletions(-) create mode 100644 Projects/Superalgos/TS/Utilities/ErrorHandlingFunctions.js diff --git a/Projects/ProjectsSchema.json b/Projects/ProjectsSchema.json index 449c49473..1dc8858e6 100644 --- a/Projects/ProjectsSchema.json +++ b/Projects/ProjectsSchema.json @@ -497,6 +497,12 @@ "propertyName": "docsFunctions", "functionName": "newSuperalgosUtilitiesDocsFunctions", "fileName": "DocsFunctions.js" + }, + { + "name": "Error Handling Functions", + "propertyName": "errorHandlingFunctions", + "functionName": "newSuperalgosUtilitiesErrorHandlingFunctions", + "fileName": "ErrorHandlingFunctions.js" } ], "taskModules": [ diff --git a/Projects/Superalgos/TS/Bot-Modules/API-Data-Fetcher-Bot/FetchingProcess.js b/Projects/Superalgos/TS/Bot-Modules/API-Data-Fetcher-Bot/FetchingProcess.js index 5890c02b9..9b70e3d62 100644 --- a/Projects/Superalgos/TS/Bot-Modules/API-Data-Fetcher-Bot/FetchingProcess.js +++ b/Projects/Superalgos/TS/Bot-Modules/API-Data-Fetcher-Bot/FetchingProcess.js @@ -8,7 +8,7 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { start: start }; - let fileStorage = TS.projects.superalgos.taskModules.fileStorage.newFileStorage(processIndex); + let fileStorage = TS.projects.superalgos.taskModules.fileStorage.newFileStorage(processIndex) let statusDependencies return thisObject; @@ -16,19 +16,19 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { function initialize(pStatusDependencies, callBackFunction) { try { statusDependencies = pStatusDependencies; - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE) } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] initialize -> err = " + err.stack); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + "[ERROR] initialize -> err = " + err.stack) + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } function start(callBackFunction) { try { if (TS.projects.superalgos.globals.taskVariables.IS_TASK_STOPPING === true) { - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE) return } @@ -50,8 +50,8 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { if (statusDependencies.statusReports.get(reportKey).status === "Status Report is corrupt.") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. "); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE); + "[ERROR] start -> getContextVariables -> Can not continue because dependecy Status Report is corrupt. ") + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_RETRY_RESPONSE) return; } @@ -61,14 +61,14 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> getContextVariables -> err = " + err.stack); + "[ERROR] start -> getContextVariables -> err = " + err.stack) if (err.message === "Cannot read property 'file' of undefined") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> Check the bot Status Dependencies. "); + "[HINT] start -> getContextVariables -> Check the bot Status Dependencies. ") TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[HINT] start -> getContextVariables -> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys)); + "[HINT] start -> getContextVariables -> Dependencies loaded -> keys = " + JSON.stringify(statusDependencies.keys)) } - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } @@ -77,7 +77,8 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { processNode = TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent if (TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].apiMapReference === undefined) { - throwHandledException( + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', undefined, 'API Map Reference Node Missing', TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex] @@ -86,7 +87,8 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { let apiMap = TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].apiMapReference.referenceParent if (apiMap === undefined) { - throwHandledException( + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', undefined, 'Reference Parent Missing', TS.projects.superalgos.globals.taskConstants.TASK_NODE.bot.processes[processIndex].apiMapReference @@ -99,8 +101,9 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { let protocol = "https" // default value if (apiMap.config.hostName === undefined || apiMap.config.hostName === "") { - throwHandledException( - {missingProperty: "hostName"}, + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', + { missingProperty: "hostName" }, 'Config Property Missing', apiMap ) @@ -121,14 +124,16 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { } if (apiMap.apiVersions.length === 0) { - throwHandledException( + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', undefined, 'API Version Node Missing', apiMap ) } if (processNode.processOutput === undefined) { - throwHandledException( + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', undefined, 'Process Output Node Missing', processNode @@ -188,7 +193,8 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { to a certain enpoint. */ if (endpointNodeFound === undefined) { - throwHandledException( + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', undefined, 'API Response Field Not Descendant From Endpoint', apiResponseField @@ -207,7 +213,8 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { /* We can not reference fields from different enpoints. */ - throwHandledException( + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', undefined, 'More Than Two Endpoints Detected', apiResponseField @@ -223,7 +230,8 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { has an API Response Field Reference child, and that this one is referencing an API Response Field. */ - throwHandledException( + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', undefined, 'API Endpoint Not Found', productDefinition.record @@ -403,8 +411,8 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { function sleep(ms) { return new Promise((resolve) => { - setTimeout(resolve, ms); - }); + setTimeout(resolve, ms) + }) } } @@ -414,7 +422,7 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { Now that we have the endpointNode, the parameters and all the information needed to place the call to the API. */ - let httpClient = require('https'); + let httpClient = require('https') let url = protocol + '://' + hostName + portNumber + @@ -453,7 +461,8 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { if (apiResponseSchemaNode === undefined) { errorCodeReceived = true - throwHandledException( + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', { resposeCodeReceived: response.statusCode, detais: 'The response code ' + response.statusCode + ' received is not associated with any API Query Response node.' }, 'Unexpected API Response Code', endpointNode @@ -486,7 +495,7 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { if (apiQueryResponse.config.isError === true) { errorCodeReceived = true TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> getApiResponseSchema -> API Response is an Error -> responseCode = " + responseCode); + "[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> getApiResponseSchema -> API Response is an Error -> responseCode = " + responseCode) } return } @@ -516,7 +525,7 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { */ if (apiResponseReceivedText.substring(0, 1) !== "{") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> onEnd -> Unexpected Response. Not an JSON Object. -> apiResponseReceivedText = " + apiResponseReceivedText); + "[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> onEnd -> Unexpected Response. Not an JSON Object. -> apiResponseReceivedText = " + apiResponseReceivedText) resolve('UNEXPECTED_API_RESPONSE') return } @@ -529,7 +538,7 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { */ if (apiResponseReceivedText.substring(0, 1) !== "[") { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> onEnd -> Unexpected Response. Not an Array with Data. -> apiResponseReceivedText = " + apiResponseReceivedText); + "[WARN] start -> startProcess -> fetchAllPages -> fetchAPIData -> onResponse -> onEnd -> Unexpected Response. Not an Array with Data. -> apiResponseReceivedText = " + apiResponseReceivedText) resolve('UNEXPECTED_API_RESPONSE') return } @@ -576,8 +585,9 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { break } default: { - throwHandledException( - { datasetType: dataset.config.codeName}, + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', + { datasetType: dataset.config.codeName }, 'Unsupported Dataset Type', dataset ) @@ -755,7 +765,8 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { /* There must be a Record Property with codeName 'timestamp' defined. */ - throwHandledException( + TS.projects.superalgos.utilities.errorHandlingFunctions.throwHandledException( + 'API Data Fetcher Bot', undefined, 'Timestamp Record Property Missing', productDefinition.record @@ -782,7 +793,7 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { if (response.err !== undefined && response.err.result !== TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> startProcess -> readDatasetFile -> Could read file. -> filePath = " + filePath + "/" + fileName); + "[ERROR] start -> startProcess -> readDatasetFile -> Could read file. -> filePath = " + filePath + "/" + fileName) throw (response.err) } else { existingFileContent = text @@ -801,11 +812,11 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { let fileName = 'Data.json' let filePath = TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).FILE_PATH_ROOT + "/Output/" + productDefinition.config.codeName + "/" + outputDataset.referenceParent.config.codeName + extraFilePath - let response = await fileStorage.asyncCreateTextFile(filePath + '/' + fileName, existingFileContent + '\n'); + let response = await fileStorage.asyncCreateTextFile(filePath + '/' + fileName, existingFileContent + '\n') if (response.err !== undefined && response.err.result !== TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> startProcess -> saveDatasetFile -> Could not save file. -> filePath = " + filePath + "/" + fileName); + "[ERROR] start -> startProcess -> saveDatasetFile -> Could not save file. -> filePath = " + filePath + "/" + fileName) throw (response.err) } } @@ -877,8 +888,8 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> startProcess -> err = " + err.stack); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + "[ERROR] start -> startProcess -> err = " + err.stack) + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } @@ -900,61 +911,24 @@ exports.newSuperalgosBotModulesFetchingProcess = function (processIndex) { function onSaved(err) { if (err.result !== TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE.result) { TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> writeStatusReport -> onSaved -> err = " + err.stack); - callBackFunction(err); + "[ERROR] start -> writeStatusReport -> onSaved -> err = " + err.stack) + callBackFunction(err) return; } - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE); + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_OK_RESPONSE) } } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> writeStatusReport -> err = " + err.stack); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + "[ERROR] start -> writeStatusReport -> err = " + err.stack) + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } } catch (err) { TS.projects.superalgos.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.superalgos.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, - "[ERROR] start -> err = " + err.stack); - callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE); + "[ERROR] start -> err = " + err.stack) + callBackFunction(TS.projects.superalgos.globals.standardResponses.DEFAULT_FAIL_RESPONSE) } } - function throwHandledException( - err, - message, - node - ) { - if (err === undefined) { - err = { - message: message - } - } - /* - This is what the Docs Space will get. - */ - let docs = { - project: 'Superalgos', - category: 'Topic', - type: 'TS API Data Fetcher Bot Error - ' + message, - placeholder: {} - } - TS.projects.superalgos.utilities.docsFunctions.buildPlaceholder( - docs, - err, - node.name, - node.code, - node.config, - node.value, - err - ) - /* - This will be needed for the process level error handling. Must be added - here after the buildPlaceholder function call. - */ - err.docs = docs - err.node = node - - throw (err) - } } diff --git a/Projects/Superalgos/TS/Utilities/ErrorHandlingFunctions.js b/Projects/Superalgos/TS/Utilities/ErrorHandlingFunctions.js new file mode 100644 index 000000000..f2a1a7809 --- /dev/null +++ b/Projects/Superalgos/TS/Utilities/ErrorHandlingFunctions.js @@ -0,0 +1,51 @@ +exports.newSuperalgosUtilitiesErrorHandlingFunctions = function () { + + let thisObject = { + throwHandledException: throwHandledException + } + + return thisObject + + /* + This function helps Bots to integrate their error handling to the In-App-Docs. + */ + function throwHandledException( + source, // The Bot Type where the handled exception occured. This will be part of the Doc's page name. + err, // The Error object available, if any. + message, // The Message, which will be part of the Docs page name. + node // The closest node related to the exception. + ) { + if (err === undefined) { + err = { + message: message + } + } + /* + This is what the Docs Space will get. + */ + let docs = { + project: 'Superalgos', + category: 'Topic', + type: 'TS ' + source + ' Error - ' + message, + placeholder: {} + } + TS.projects.superalgos.utilities.docsFunctions.buildPlaceholder( + docs, + err, + node.name, + node.code, + node.config, + node.value, + err + ) + /* + This will be needed for the process level error handling. Must be added + here after the buildPlaceholder function call otherwise it would be included as a + placeholder. + */ + err.docs = docs + err.node = node + + throw (err) + } +} \ No newline at end of file