diff --git a/IndicatorBot.js b/IndicatorBot.js index fc28afeae..3d2ab599f 100644 --- a/IndicatorBot.js +++ b/IndicatorBot.js @@ -1,167 +1,1131 @@ -exports.newIndicatorBot = function newIndicatorBot(bot, logger, UTILITIES, FILE_STORAGE) { +exports.newIndicatorBot = function newIndicatorBot(bot, parentLogger) { + const ROOT_DIR = './'; + + const MODULE_NAME = "Indicator Process Main Loop"; const FULL_LOG = true; - const LOG_FILE_CONTENT = false; - const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000; - const MODULE_NAME = "Indicator Bot"; + let USER_BOT_MODULE; + let COMMONS_MODULE; + + const MULTI_PERIOD_MARKET = require(ROOT_DIR + 'MultiPeriodMarket'); + const MULTI_PERIOD_DAILY = require(ROOT_DIR + 'MultiPeriodDaily'); + const FILE_STORAGE = require('./FileStorage.js'); + let fileStorage = FILE_STORAGE.newFileStorage(parentLogger); + + const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); + let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. + + let nextLoopTimeoutHandle; + let checkLoopHealthHandle; let thisObject = { initialize: initialize, - finalize: finalize, - start: start + run: run }; - let utilities = UTILITIES.newCloudUtilities(logger); - let fileStorage = FILE_STORAGE.newFileStorage(logger); - - const COMMONS = require('./Commons.js'); - let commons = COMMONS.newCommons(bot, logger, UTILITIES, FILE_STORAGE); + let processConfig; return thisObject; - function finalize() { - thisObject = undefined - utilities = undefined - fileStorage = undefined - commons = undefined - } - - function initialize(callBackFunction) { + function initialize(pProcessConfig, callBackFunction) { try { + if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } - logger.fileName = MODULE_NAME; - logger.initialize(); + processConfig = pProcessConfig; - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } + if (bot.definedByUI === true) { + /* The code of the bot is defined at the UI. No need to load a file with the code. */ + callBackFunction(global.DEFAULT_OK_RESPONSE); + return + } - callBackFunction(global.DEFAULT_OK_RESPONSE); + /* This bot is not ready for taking its code from the UI, then we need to load it from its repo. */ + let filePath = bot.dataMine + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.codeName + filePath += "/User.Bot.js" + + fileStorage.getTextFile(filePath, onBotDownloaded); + + function onBotDownloaded(err, text) { + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> err = " + err.message); + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> filePath = " + filePath); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + + USER_BOT_MODULE = {} + USER_BOT_MODULE.newUserBot = eval(text); // TODO This needs to be changed function + + filePath = bot.dataMine + "/" + "bots" + "/" + bot.repo; + filePath += "/Commons.js" + + fileStorage.getTextFile(filePath, onCommonsDownloaded); + + function onCommonsDownloaded(err, text) { + + if (err.result !== global.DEFAULT_OK_RESPONSE.result) { + parentLogger.write(MODULE_NAME, "[WARN] initialize -> onBotDownloaded -> onCommonsDownloaded -> Commons not found: " + err.code || err.message); + callBackFunction(global.DEFAULT_OK_RESPONSE); + return; + } + COMMONS_MODULE = {} + COMMONS_MODULE.newCommons = eval(text); // TODO This needs to be changed function + + callBackFunction(global.DEFAULT_OK_RESPONSE); + } + } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); + parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } - function start(dataFiles, timeFrame, timeFrameLabel, currentDay, interExecutionMemory, callBackFunction) { + function run(callBackFunction) { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); } + if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] run -> Entering function."); } - let products = {} - let mainDependency = {} - let processingDailyFiles + bot.enableCheckLoopHealth = true; - if (currentDay !== undefined) { - processingDailyFiles = true + let fixedTimeLoopIntervalHandle; + + /* Errors sent to the UI */ + bot.processError = processError + + /* Heartbeats sent to the UI */ + bot.processHeartBeat = processHeartBeat + + if (bot.runAtFixedInterval === true) { + fixedTimeLoopIntervalHandle = setInterval(loop, bot.fixedInterval); } else { - processingDailyFiles = false + loop(); } - /* The first phase here is about checking that we have everything we need at the definition level. */ - let dataDependencies = bot.processNode.referenceParent.processDependencies.dataDependencies - if (commons.validateDataDependencies(dataDependencies, callBackFunction) !== true) { return } + function loop() { - let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets - if (commons.validateOutputDatasets(outputDatasets, callBackFunction) !== true) { return } + try { - /* The second phase is about transforming the inputs into a format that can be used to apply the user defined code. */ - commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame) - - /* During the third phase, we need to generate the data of the different products this process produces an output */ - for (let i = 0; i < outputDatasets.length; i++) { - - let outputDatasetNode = outputDatasets[i] - let jsonData // Just build data as Json objects - let outputData // Data built as a result of applying user defined code and formulas at the Data Building Procedure - let singularVariableName // Name of the variable for this product - let recordDefinition // Record as defined by the user at the UI - let fileContent // Here we store the contents of the new data built just before writing it to a file. - let resultsWithIrregularPeriods // A product will have irregular periods when the User Code inserts new result records at will, in contrast with normal procedure where the platform insert one record per loop execution. - - /* - For each outputDatasetNode in our process output, we will build the information based on our input products. - */ - - recordDefinition = outputDatasetNode.referenceParent.parentNode.record - singularVariableName = outputDatasetNode.referenceParent.parentNode.config.singularVariableName - - /* Check Irregular Periods */ - - if (outputDatasetNode.referenceParent.parentNode.dataBuilding.loop.javascriptCode !== undefined) { - if (outputDatasetNode.referenceParent.parentNode.dataBuilding.loop.javascriptCode.code.indexOf('results.push') >= 0) { - resultsWithIrregularPeriods = true + function pad(str, max) { + str = str.toString(); + return str.length < max ? pad(" " + str, max) : str; } - } - /* Build the data */ - jsonData = commons.dataBuildingProcedure( - products, - mainDependency, - recordDefinition, - outputDatasetNode.referenceParent.parentNode.dataBuilding, - singularVariableName, - outputDatasetNode.referenceParent.parentNode.config.codeName, - timeFrame, - timeFrameLabel, - resultsWithIrregularPeriods, - interExecutionMemory, - processingDailyFiles, - currentDay - ) + /* For each loop we want to create a new log file. */ - /* Add the calculated properties */ - if (outputDatasetNode.referenceParent.parentNode.calculations !== undefined) { - outputData = commons.calculationsProcedure(jsonData, recordDefinition, outputDatasetNode.referenceParent.parentNode.calculations, singularVariableName, timeFrame) - } else { - outputData = jsonData - } - products[outputDatasetNode.referenceParent.parentNode.config.pluralVariableName] = outputData - } + if (logger !== undefined) { + logger.finalize() + } + logger = DEBUG_MODULE.newDebugLog(); + global.LOGGER_MAP.set(MODULE_NAME, logger) + logger.bot = bot; + logger.initialize(); - /*At the fourth and last phase, we will save the new information generated into files corresponding to each output outputDatasetNode.*/ - let totalFilesWritten = 0 - for (let i = 0; i < outputDatasets.length; i++) { - let outputDatasetNode = outputDatasets[i] - let outputData = products[outputDatasetNode.referenceParent.parentNode.config.pluralVariableName] - let resultsWithIrregularPeriods // A product will have irregular periods when the User Code inserts new result records at will, in contrast with normal procedure where the platform insert one record per loop execution. - let contextSummary = {} + bot.loopCounter++; + bot.loopStartTime = new Date().valueOf(); - /* Check Irregular Periods */ - if (outputDatasetNode.referenceParent.parentNode.dataBuilding.loop.javascriptCode.code.indexOf('results.push') >= 0) { - resultsWithIrregularPeriods = true - } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> Entering function."); } - /* Simplifying the access to basic info */ + /* We tell the UI that we are running. */ + processHeartBeat() - contextSummary.dataset = outputDatasetNode.referenceParent.config.codeName - contextSummary.product = outputDatasetNode.referenceParent.parentNode.config.codeName - contextSummary.bot = outputDatasetNode.referenceParent.parentNode.parentNode.config.codeName - contextSummary.dataMine = outputDatasetNode.referenceParent.parentNode.parentNode.parentNode.config.codeName + /* We define here all the modules that the rest of the infraestructure, including the bots themselves can consume. */ - /* This stuff is still hardcoded and unresolved. */ - contextSummary.botVersion = { - "major": 1, - "minor": 0 - } - contextSummary.dataSetVersion = "dataSet.V1" + const UTILITIES = require(ROOT_DIR + 'CloudUtilities'); + const STATUS_REPORT = require(ROOT_DIR + 'StatusReport'); + const STATUS_DEPENDENCIES = require(ROOT_DIR + 'StatusDependencies'); + const DATA_DEPENDENCIES = require(ROOT_DIR + 'DataDependencies'); + const DATA_SET = require(ROOT_DIR + 'DataSet'); + const PROCESS_EXECUTION_EVENTS = require(ROOT_DIR + 'ProcessExecutionEvents'); + const PROCESS_OUTPUT = require(ROOT_DIR + 'ProcessOutput'); - let fileContent = commons.generateFileContent(outputData, outputDatasetNode.referenceParent.parentNode.record, resultsWithIrregularPeriods, processingDailyFiles, currentDay, callBackFunction) - commons.writeFile(contextSummary, fileContent, anotherFileWritten, processingDailyFiles, timeFrameLabel, currentDay, callBackFunction) - } + /* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */ + bot.processDatetime = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution. - function anotherFileWritten() { - totalFilesWritten++ - if (totalFilesWritten === outputDatasets.length) { - callBackFunction(global.DEFAULT_OK_RESPONSE); + /* High level log entry */ + + console.log(new Date().toISOString() + " " + pad(bot.exchange, 20) + " " + pad(bot.market.baseAsset + '/' + bot.market.quotedAsset, 10) + " " + pad(bot.codeName, 30) + " " + pad(bot.process, 30) + + " Main Loop # " + pad(Number(bot.loopCounter), 8)) + + /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */ + + let processExecutionEvents + let userBot; + let processFramework; + let statusDependencies; + let dataDependencies; + + let nextWaitTime; + + initializeProcessExecutionEvents(); + + function initializeProcessExecutionEvents() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> Entering function."); } + + processExecutionEvents = PROCESS_EXECUTION_EVENTS.newProcessExecutionEvents(bot, logger) + + processExecutionEvents.initialize(onInizialized); + + function onInizialized(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Entering function."); } + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Execution finished well."); + startProcessExecutionEvents() + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + processStopped() + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + function startProcessExecutionEvents() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> Entering function."); } + + processExecutionEvents.start(onStarted); + + function onStarted(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Entering function."); } + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Execution finished well."); + + if (global.STOP_TASK_GRACEFULLY === true) { + loopControl() + return + } + + initializeStatusDependencies(); + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessExecutionEvents -> onStarted -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + processStopped() + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + function initializeStatusDependencies() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeStatusDependencies -> Entering function."); } + + statusDependencies = STATUS_DEPENDENCIES.newStatusDependencies(bot, logger, STATUS_REPORT, UTILITIES, PROCESS_OUTPUT); + + statusDependencies.initialize(onInizialized); + + function onInizialized(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeStatusDependencies -> onInizialized -> Entering function."); } + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeStatusDependencies -> onInizialized -> Execution finished well."); + initializeDataDependencies(); + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeStatusDependencies -> onInizialized -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + processStopped() + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> Unhandled err.result received. -> err = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + function initializeDataDependencies() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> Entering function."); } + + dataDependencies = DATA_DEPENDENCIES.newDataDependencies(bot, logger, DATA_SET); + + dataDependencies.initialize(onInizialized); + + function onInizialized(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Entering function."); } + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Execution finished well."); } + + /* If the process is configured to run inside a framework, we continue there, otherwise we run the bot directly. */ + if (processConfig.framework === undefined) { + initializeUserBot(); + return; + } + + switch (processConfig.framework.name) { + case 'Multi-Period-Market': { + processFramework = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, UTILITIES, FILE_STORAGE); + intitializeProcessFramework(); + break; + } + case 'Multi-Period-Daily': { + processFramework = MULTI_PERIOD_DAILY.newMultiPeriodDaily(bot, logger, UTILITIES, FILE_STORAGE); + intitializeProcessFramework(); + break; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Process Framework not Supported."); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Process Framework Name = " + processConfig.framework.name); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + } + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeDataDependencies -> onInizialized -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + processStopped() + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Unhandled err.result received. -> err = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + function initializeUserBot() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeUserBot -> Entering function."); } + + usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, FILE_STORAGE); + + usertBot.initialize(statusDependencies, onInizialized); + + function onInizialized(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeUserBot -> onInizialized -> Entering function."); } + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeUserBot -> onInizialized -> Execution finished well."); + startUserBot(); + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeUserBot -> onInizialized -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + processStopped() + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + case global.CUSTOM_OK_RESPONSE.result: { + + switch (err.message) { + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized > Unhandled custom response received. -> err = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + } + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> Unhandled err.result received. -> err = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + function startUserBot() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startUserBot -> Entering function."); } + + usertBot.start(onFinished); + + function onFinished(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startUserBot -> onFinished -> Entering function."); } + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write(MODULE_NAME, "[INFO] run -> loop -> startUserBot -> onFinished -> Execution finished well."); + finishProcessExecutionEvents() + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[WARN] run -> loop -> startUserBot -> onFinished -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + processStopped() + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + case global.CUSTOM_OK_RESPONSE.result: { + + switch (err.message) { + case "Dependency does not exist.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> startUserBot -> onFinished -> Dependency does not exist. This Loop will go to sleep."); + nextWaitTime = 'Sleep'; + loopControl(nextWaitTime); + return; + } + case "Dependency not ready.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> startUserBot -> onFinished -> Dependency not ready. Will Retry Later."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> Unhandled custom response received. -> err = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + } + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> Unhandled err.result received. -> err = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + function intitializeProcessFramework() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> Entering function."); } + + processFramework.initialize(processConfig, statusDependencies, dataDependencies, onInizialized); + + function onInizialized(err) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> onInizialized -> Entering function."); } + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> onInizialized -> Execution finished well."); + startProcessFramework(); + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[WARN] run -> loop -> intitializeProcessFramework -> onInizialized -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + processStopped() + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + case global.CUSTOM_OK_RESPONSE.result: { + + switch (err.message) { + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized > Unhandled custom response received. -> err = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + } + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Unhandled err.result received. -> err = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + function startProcessFramework() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> Entering function."); } + + processFramework.start(onFinished); + + function onFinished(err) { + + try { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Entering function."); } + processFramework.finalize() + processFramework = undefined + dataDependencies.finalize() + dataDependencies = undefined + statusDependencies.finalize() + statusDependencies = undefined + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Execution finished well."); + finishProcessExecutionEvents() + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + processStopped() + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + case global.CUSTOM_OK_RESPONSE.result: { + + switch (err.message) { + case "Dependency does not exist.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Dependency does not exist. This Loop will go to sleep."); + nextWaitTime = 'Sleep'; + loopControl(nextWaitTime); + return; + } + case "Dependency not ready.": { + logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Dependency not ready. This Loop will go to sleep."); + nextWaitTime = 'Sleep'; + loopControl(nextWaitTime); + return; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled custom response received. -> err = " + err.message); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + } + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled err.result received. -> err = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + function finishProcessExecutionEvents() { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> Entering function."); } + + processExecutionEvents.finish(onFinished); + + function onFinished(err) { + try { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Entering function."); } + + processExecutionEvents.finalize() + processExecutionEvents = undefined + + switch (err.result) { + case global.DEFAULT_OK_RESPONSE.result: { + logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Execution finished well."); + nextWaitTime = 'Normal'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. + logger.write(MODULE_NAME, "[WARN] run -> loop -> finishProcessExecutionEvents -> onFinished -> Retry Later. Requesting Execution Retry."); + nextWaitTime = 'Retry'; + loopControl(nextWaitTime); + return; + } + case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. + processStopped() + logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Operation Failed. Aborting the process."); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + return; + } + default: { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err.result = " + err.result); + logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err = " + err.message); + + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); + } + } + + function loopControl(nextWaitTime) { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> nextWaitTime = " + nextWaitTime); } + + /* We show we reached the end of the loop. */ + + processHeartBeat() + + /* Here we check if we must stop the loop gracefully. */ + + shallWeStop(onStop, onContinue); + + function onStop() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> onStop -> Entering function."); } + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> onStop -> Stopping the Loop Gracefully. See you next time!"); } + + if (global.WRITE_LOGS_TO_FILES === 'true') { + logger.persist(); + } + + processStopped() + callBackFunction(global.DEFAULT_OK_RESPONSE); + return; + + } + + function onContinue() { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> onContinue -> Entering function."); } + + /* Indicator bots are going to be executed after a configured period of time after the last execution ended. This is to avoid overlapping executions. */ + + switch (nextWaitTime) { + case 'Normal': { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.normalWaitTime / 1000) + " seconds."); } + if (processConfig.deadWaitTime > 0) { + checkLoopHealthHandle = setTimeout(checkLoopHealth, processConfig.deadWaitTime, bot.loopCounter); + } + nextLoopTimeoutHandle = setTimeout(loop, processConfig.normalWaitTime); + processHeartBeat(undefined, undefined, "Waiting " + processConfig.normalWaitTime / 1000 + " seconds for next execution.") + if (global.WRITE_LOGS_TO_FILES === 'true') { + logger.persist(); + } + } + break; + case 'Retry': { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.retryWaitTime / 1000) + " seconds."); } + if (processConfig.deadWaitTime > 0) { + checkLoopHealthHandle = setTimeout(checkLoopHealth, processConfig.deadWaitTime, bot.loopCounter); + } + nextLoopTimeoutHandle = setTimeout(loop, processConfig.retryWaitTime); + processHeartBeat(undefined, undefined, "Trying to recover from some problem. Waiting " + processConfig.retryWaitTime / 1000 + " seconds for next execution.") + logger.persist(); + } + break; + case 'Sleep': { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.sleepWaitTime / 60000) + " minutes."); } + nextLoopTimeoutHandle = setTimeout(loop, processConfig.sleepWaitTime); + processHeartBeat(undefined, undefined, "Waiting " + processConfig.sleepWaitTime / 60000 + " minutes for next execution.") + logger.persist(); + } + break; + case 'Coma': { + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.comaWaitTime / 3600000) + " hours."); } + nextLoopTimeoutHandle = setTimeout(loop, processConfig.comaWaitTime); + processHeartBeat(undefined, undefined, "Waiting " + processConfig.comaWaitTime / 3600000 + " hours for next execution.") + logger.persist(); + } + break; + } + } + } + + function checkLoopHealth(pLastLoop) { + + if (bot.enableCheckLoopHealth === false || global.STOP_TASK_GRACEFULLY === true) { + + logger.write(MODULE_NAME, "[WARN] run -> loop -> checkLoopHealth -> bot.enableCheckLoopHealth = " + bot.enableCheckLoopHealth); + + return; + } // This gets disabled anytime the Main Loop is shut down by any condition. + + if (bot.loopCounter <= pLastLoop + 1) { // This means that the next loop started but also stopped executing abruptally. + + let now = new Date().valueOf(); + + if (now - bot.loopStartTime > processConfig.deadWaitTime) { + + logger.write(MODULE_NAME, "[ERROR] run -> loop -> checkLoopHealth -> Dead loop found -> pLastLoop = " + pLastLoop); + console.log((new Date().toISOString() + " [ERROR] run -> loop -> checkLoopHealth -> " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " Loop # " + pad(Number(bot.loopCounter), 5) + " found dead. Resurrecting it now.")); + + logger.persist(); // We persist the logs of the failed execution. + clearTimeout(nextLoopTimeoutHandle); // We cancel the timeout in case the original loop was still running and schedulled to reexecute. + loop(); // We restart the loop so that the processing can continue. + + } else { + + console.log((new Date().toISOString() + " [WARN] run -> loop -> checkLoopHealth -> " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " Loop # " + pad(Number(bot.loopCounter), 5) + " found delayed but still alive. No action taken.")); + + } + } + } + + function shallWeStop(stopCallBack, continueCallBack) { + + try { + + /* IMPORTANT: This function is exactly the same on the 3 modules. */ + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> shallWeStop -> Entering function. "); } + + if (!global.STOP_TASK_GRACEFULLY) { + continueCallBack(); + } else { + stopCallBack(); + } + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] run -> loop -> shallWeStop -> err = " + err.stack); + logger.persist(); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return; + } + } + } catch (err) { + parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = " + err.stack); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; + callBackFunction(err); } } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack); + + function processHeartBeat(processingDate, percentage, status) { + let event = { + seconds: (new Date()).getSeconds(), + processingDate: processingDate, + percentage: percentage, + status: status + } + global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Heartbeat', event) + } + + function processError(node, errorMessage) { + let event = { + nodeName: node.name, + nodeType: node.type, + nodeId: node.id, + errorMessage: errorMessage + } + global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Error', event) + } + + function processStopped() { + global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Stopped') + } + + } catch (err) { + parentLogger.write(MODULE_NAME, "[ERROR] run -> err = " + err.stack); + clearInterval(fixedTimeLoopIntervalHandle); + clearTimeout(nextLoopTimeoutHandle); + clearTimeout(checkLoopHealthHandle); + bot.enableCheckLoopHealth = false; callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js deleted file mode 100644 index dbf0c3b82..000000000 --- a/IndicatorBotProcessMainLoop.js +++ /dev/null @@ -1,1122 +0,0 @@ -exports.newIndicatorBotProcessMainLoop = function newIndicatorBotProcessMainLoop(bot, parentLogger) { - - const ROOT_DIR = './'; - - const MODULE_NAME = "Indicator Process Main Loop"; - const FULL_LOG = true; - - let USER_BOT_MODULE; - let COMMONS_MODULE; - - const MULTI_PERIOD_MARKET = require(ROOT_DIR + 'MultiPeriodMarket'); - const MULTI_PERIOD_DAILY = require(ROOT_DIR + 'MultiPeriodDaily'); - const FILE_STORAGE = require('./FileStorage.js'); - let fileStorage = FILE_STORAGE.newFileStorage(parentLogger); - - const DEBUG_MODULE = require(ROOT_DIR + 'DebugLog'); - let logger; // We need this here in order for the loopHealth function to work and be able to rescue the loop when it gets in trouble. - - let nextLoopTimeoutHandle; - let checkLoopHealthHandle; - - let thisObject = { - initialize: initialize, - run: run - }; - - let processConfig; - - return thisObject; - - function initialize(pProcessConfig, callBackFunction) { - - try { - if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } - - processConfig = pProcessConfig; - - if (bot.definedByUI === true) { - /* The code of the bot is defined at the UI. No need to load a file with the code. */ - callBackFunction(global.DEFAULT_OK_RESPONSE); - return - } - - /* This bot is not ready for taking its code from the UI, then we need to load it from its repo. */ - - let filePath = bot.dataMine + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.codeName - filePath += "/User.Bot.js" - - fileStorage.getTextFile(filePath, onBotDownloaded); - - function onBotDownloaded(err, text) { - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> err = " + err.message); - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> onInizialized -> onBotDownloaded -> filePath = " + filePath); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - - USER_BOT_MODULE = {} - USER_BOT_MODULE.newUserBot = eval(text); // TODO This needs to be changed function - - filePath = bot.dataMine + "/" + "bots" + "/" + bot.repo; - filePath += "/Commons.js" - - fileStorage.getTextFile(filePath, onCommonsDownloaded); - - function onCommonsDownloaded(err, text) { - - if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - parentLogger.write(MODULE_NAME, "[WARN] initialize -> onBotDownloaded -> onCommonsDownloaded -> Commons not found: " + err.code || err.message); - callBackFunction(global.DEFAULT_OK_RESPONSE); - return; - } - COMMONS_MODULE = {} - COMMONS_MODULE.newCommons = eval(text); // TODO This needs to be changed function - - callBackFunction(global.DEFAULT_OK_RESPONSE); - } - } - } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - function run(callBackFunction) { - - try { - - if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] run -> Entering function."); } - - bot.enableCheckLoopHealth = true; - - let fixedTimeLoopIntervalHandle; - - /* Errors sent to the UI */ - bot.processError = processError - - /* Heartbeats sent to the UI */ - bot.processHeartBeat = processHeartBeat - - if (bot.runAtFixedInterval === true) { - fixedTimeLoopIntervalHandle = setInterval(loop, bot.fixedInterval); - } else { - loop(); - } - - function loop() { - - try { - - function pad(str, max) { - str = str.toString(); - return str.length < max ? pad(" " + str, max) : str; - } - - /* For each loop we want to create a new log file. */ - - if (logger !== undefined) { - logger.finalize() - } - logger = DEBUG_MODULE.newDebugLog(); - global.LOGGER_MAP.set(MODULE_NAME, logger) - logger.bot = bot; - logger.initialize(); - - bot.loopCounter++; - bot.loopStartTime = new Date().valueOf(); - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> Entering function."); } - - /* We tell the UI that we are running. */ - processHeartBeat() - - /* We define here all the modules that the rest of the infraestructure, including the bots themselves can consume. */ - - const UTILITIES = require(ROOT_DIR + 'CloudUtilities'); - const STATUS_REPORT = require(ROOT_DIR + 'StatusReport'); - const STATUS_DEPENDENCIES = require(ROOT_DIR + 'StatusDependencies'); - const DATA_DEPENDENCIES = require(ROOT_DIR + 'DataDependencies'); - const DATA_SET = require(ROOT_DIR + 'DataSet'); - const PROCESS_EXECUTION_EVENTS = require(ROOT_DIR + 'ProcessExecutionEvents'); - const PROCESS_OUTPUT = require(ROOT_DIR + 'ProcessOutput'); - - /* We define the datetime for the process that we are running now. This will be the official processing time for both the infraestructure and the bot. */ - - bot.processDatetime = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution. - - /* High level log entry */ - - console.log(new Date().toISOString() + " " + pad(bot.exchange, 20) + " " + pad(bot.market.baseAsset + '/' + bot.market.quotedAsset, 10) + " " + pad(bot.codeName, 30) + " " + pad(bot.process, 30) - + " Main Loop # " + pad(Number(bot.loopCounter), 8)) - - /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */ - - let processExecutionEvents - let userBot; - let processFramework; - let statusDependencies; - let dataDependencies; - - let nextWaitTime; - - initializeProcessExecutionEvents(); - - function initializeProcessExecutionEvents() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> Entering function."); } - - processExecutionEvents = PROCESS_EXECUTION_EVENTS.newProcessExecutionEvents(bot, logger) - - processExecutionEvents.initialize(onInizialized); - - function onInizialized(err) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Entering function."); } - - switch (err.result) { - case global.DEFAULT_OK_RESPONSE.result: { - logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Execution finished well."); - startProcessExecutionEvents() - return; - } - case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Retry Later. Requesting Execution Retry."); - nextWaitTime = 'Retry'; - loopControl(nextWaitTime); - return; - } - case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - processStopped() - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Operation Failed. Aborting the process."); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Unhandled err.result received. -> err = " + err.message); - - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - function startProcessExecutionEvents() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> Entering function."); } - - processExecutionEvents.start(onStarted); - - function onStarted(err) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Entering function."); } - - switch (err.result) { - case global.DEFAULT_OK_RESPONSE.result: { - logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessExecutionEvents -> onStarted -> Execution finished well."); - - if (global.STOP_TASK_GRACEFULLY === true) { - loopControl() - return - } - - initializeStatusDependencies(); - return; - } - case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessExecutionEvents -> onStarted -> Retry Later. Requesting Execution Retry."); - nextWaitTime = 'Retry'; - loopControl(nextWaitTime); - return; - } - case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - processStopped() - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Operation Failed. Aborting the process."); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Unhandled err.result received. -> err = " + err.message); - - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - function initializeStatusDependencies() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeStatusDependencies -> Entering function."); } - - statusDependencies = STATUS_DEPENDENCIES.newStatusDependencies(bot, logger, STATUS_REPORT, UTILITIES, PROCESS_OUTPUT); - - statusDependencies.initialize(onInizialized); - - function onInizialized(err) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeStatusDependencies -> onInizialized -> Entering function."); } - - switch (err.result) { - case global.DEFAULT_OK_RESPONSE.result: { - logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeStatusDependencies -> onInizialized -> Execution finished well."); - initializeDataDependencies(); - return; - } - case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeStatusDependencies -> onInizialized -> Retry Later. Requesting Execution Retry."); - nextWaitTime = 'Retry'; - loopControl(nextWaitTime); - return; - } - case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - processStopped() - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> Operation Failed. Aborting the process."); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> Unhandled err.result received. -> err = " + err.message); - - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - function initializeDataDependencies() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> Entering function."); } - - dataDependencies = DATA_DEPENDENCIES.newDataDependencies(bot, logger, DATA_SET); - - dataDependencies.initialize(onInizialized); - - function onInizialized(err) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Entering function."); } - - switch (err.result) { - case global.DEFAULT_OK_RESPONSE.result: { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Execution finished well."); } - - /* If the process is configured to run inside a framework, we continue there, otherwise we run the bot directly. */ - if (processConfig.framework === undefined) { - initializeUserBot(); - return; - } - - switch (processConfig.framework.name) { - case 'Multi-Period-Market': { - processFramework = MULTI_PERIOD_MARKET.newMultiPeriodMarket(bot, logger, UTILITIES, FILE_STORAGE); - intitializeProcessFramework(); - break; - } - case 'Multi-Period-Daily': { - processFramework = MULTI_PERIOD_DAILY.newMultiPeriodDaily(bot, logger, UTILITIES, FILE_STORAGE); - intitializeProcessFramework(); - break; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Process Framework not Supported."); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Process Framework Name = " + processConfig.framework.name); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - } - return; - } - case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeDataDependencies -> onInizialized -> Retry Later. Requesting Execution Retry."); - nextWaitTime = 'Retry'; - loopControl(nextWaitTime); - return; - } - case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - processStopped() - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Operation Failed. Aborting the process."); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> Unhandled err.result received. -> err = " + err.message); - - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - function initializeUserBot() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeUserBot -> Entering function."); } - - usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, FILE_STORAGE); - - usertBot.initialize(statusDependencies, onInizialized); - - function onInizialized(err) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeUserBot -> onInizialized -> Entering function."); } - - switch (err.result) { - case global.DEFAULT_OK_RESPONSE.result: { - logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeUserBot -> onInizialized -> Execution finished well."); - startUserBot(); - return; - } - case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[WARN] run -> loop -> initializeUserBot -> onInizialized -> Retry Later. Requesting Execution Retry."); - nextWaitTime = 'Retry'; - loopControl(nextWaitTime); - return; - } - case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - processStopped() - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> Operation Failed. Aborting the process."); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - case global.CUSTOM_OK_RESPONSE.result: { - - switch (err.message) { - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized > Unhandled custom response received. -> err = " + err.message); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - } - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> Unhandled err.result received. -> err = " + err.message); - - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - function startUserBot() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startUserBot -> Entering function."); } - - usertBot.start(onFinished); - - function onFinished(err) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startUserBot -> onFinished -> Entering function."); } - - switch (err.result) { - case global.DEFAULT_OK_RESPONSE.result: { - logger.write(MODULE_NAME, "[INFO] run -> loop -> startUserBot -> onFinished -> Execution finished well."); - finishProcessExecutionEvents() - return; - } - case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[WARN] run -> loop -> startUserBot -> onFinished -> Retry Later. Requesting Execution Retry."); - nextWaitTime = 'Retry'; - loopControl(nextWaitTime); - return; - } - case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - processStopped() - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> Operation Failed. Aborting the process."); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - case global.CUSTOM_OK_RESPONSE.result: { - - switch (err.message) { - case "Dependency does not exist.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> startUserBot -> onFinished -> Dependency does not exist. This Loop will go to sleep."); - nextWaitTime = 'Sleep'; - loopControl(nextWaitTime); - return; - } - case "Dependency not ready.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> startUserBot -> onFinished -> Dependency not ready. Will Retry Later."); - nextWaitTime = 'Retry'; - loopControl(nextWaitTime); - return; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> Unhandled custom response received. -> err = " + err.message); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - } - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> Unhandled err.result received. -> err = " + err.message); - - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - function intitializeProcessFramework() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> Entering function."); } - - processFramework.initialize(processConfig, statusDependencies, dataDependencies, onInizialized); - - function onInizialized(err) { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> onInizialized -> Entering function."); } - - switch (err.result) { - case global.DEFAULT_OK_RESPONSE.result: { - logger.write(MODULE_NAME, "[INFO] run -> loop -> intitializeProcessFramework -> onInizialized -> Execution finished well."); - startProcessFramework(); - return; - } - case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[WARN] run -> loop -> intitializeProcessFramework -> onInizialized -> Retry Later. Requesting Execution Retry."); - nextWaitTime = 'Retry'; - loopControl(nextWaitTime); - return; - } - case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - processStopped() - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Operation Failed. Aborting the process."); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - case global.CUSTOM_OK_RESPONSE.result: { - - switch (err.message) { - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized > Unhandled custom response received. -> err = " + err.message); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - } - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Unhandled err.result received. -> err = " + err.message); - - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - function startProcessFramework() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> Entering function."); } - - processFramework.start(onFinished); - - function onFinished(err) { - - try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Entering function."); } - processFramework.finalize() - processFramework = undefined - dataDependencies.finalize() - dataDependencies = undefined - statusDependencies.finalize() - statusDependencies = undefined - - switch (err.result) { - case global.DEFAULT_OK_RESPONSE.result: { - logger.write(MODULE_NAME, "[INFO] run -> loop -> startProcessFramework -> onFinished -> Execution finished well."); - finishProcessExecutionEvents() - return; - } - case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Retry Later. Requesting Execution Retry."); - nextWaitTime = 'Retry'; - loopControl(nextWaitTime); - return; - } - case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - processStopped() - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Operation Failed. Aborting the process."); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - case global.CUSTOM_OK_RESPONSE.result: { - - switch (err.message) { - case "Dependency does not exist.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Dependency does not exist. This Loop will go to sleep."); - nextWaitTime = 'Sleep'; - loopControl(nextWaitTime); - return; - } - case "Dependency not ready.": { - logger.write(MODULE_NAME, "[WARN] run -> loop -> startProcessFramework -> onFinished -> Dependency not ready. This Loop will go to sleep."); - nextWaitTime = 'Sleep'; - loopControl(nextWaitTime); - return; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled custom response received. -> err = " + err.message); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - } - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Unhandled err.result received. -> err = " + err.message); - - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - function finishProcessExecutionEvents() { - - try { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> Entering function."); } - - processExecutionEvents.finish(onFinished); - - function onFinished(err) { - try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Entering function."); } - - processExecutionEvents.finalize() - processExecutionEvents = undefined - - switch (err.result) { - case global.DEFAULT_OK_RESPONSE.result: { - logger.write(MODULE_NAME, "[INFO] run -> loop -> finishProcessExecutionEvents -> onFinished -> Execution finished well."); - nextWaitTime = 'Normal'; - loopControl(nextWaitTime); - return; - } - case global.DEFAULT_RETRY_RESPONSE.result: { // Something bad happened, but if we retry in a while it might go through the next time. - logger.write(MODULE_NAME, "[WARN] run -> loop -> finishProcessExecutionEvents -> onFinished -> Retry Later. Requesting Execution Retry."); - nextWaitTime = 'Retry'; - loopControl(nextWaitTime); - return; - } - case global.DEFAULT_FAIL_RESPONSE.result: { // This is an unexpected exception that we do not know how to handle. - processStopped() - logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Operation Failed. Aborting the process."); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - return; - } - default: { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err.result = " + err.result); - logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Unhandled err.result received. -> err = " + err.message); - - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - function loopControl(nextWaitTime) { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Entering function."); } - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> nextWaitTime = " + nextWaitTime); } - - /* We show we reached the end of the loop. */ - - processHeartBeat() - - /* Here we check if we must stop the loop gracefully. */ - - shallWeStop(onStop, onContinue); - - function onStop() { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> onStop -> Entering function."); } - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> onStop -> Stopping the Loop Gracefully. See you next time!"); } - - if (global.WRITE_LOGS_TO_FILES === 'true') { - logger.persist(); - } - - processStopped() - callBackFunction(global.DEFAULT_OK_RESPONSE); - return; - - } - - function onContinue() { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> onContinue -> Entering function."); } - - /* Indicator bots are going to be executed after a configured period of time after the last execution ended. This is to avoid overlapping executions. */ - - switch (nextWaitTime) { - case 'Normal': { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.normalWaitTime / 1000) + " seconds."); } - if (processConfig.deadWaitTime > 0) { - checkLoopHealthHandle = setTimeout(checkLoopHealth, processConfig.deadWaitTime, bot.loopCounter); - } - nextLoopTimeoutHandle = setTimeout(loop, processConfig.normalWaitTime); - processHeartBeat(undefined, undefined, "Waiting " + processConfig.normalWaitTime / 1000 + " seconds for next execution.") - if (global.WRITE_LOGS_TO_FILES === 'true') { - logger.persist(); - } - } - break; - case 'Retry': { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.retryWaitTime / 1000) + " seconds."); } - if (processConfig.deadWaitTime > 0) { - checkLoopHealthHandle = setTimeout(checkLoopHealth, processConfig.deadWaitTime, bot.loopCounter); - } - nextLoopTimeoutHandle = setTimeout(loop, processConfig.retryWaitTime); - processHeartBeat(undefined, undefined, "Trying to recover from some problem. Waiting " + processConfig.retryWaitTime / 1000 + " seconds for next execution.") - logger.persist(); - } - break; - case 'Sleep': { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.sleepWaitTime / 60000) + " minutes."); } - nextLoopTimeoutHandle = setTimeout(loop, processConfig.sleepWaitTime); - processHeartBeat(undefined, undefined, "Waiting " + processConfig.sleepWaitTime / 60000 + " minutes for next execution.") - logger.persist(); - } - break; - case 'Coma': { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> loopControl -> Restarting Loop in " + (processConfig.comaWaitTime / 3600000) + " hours."); } - nextLoopTimeoutHandle = setTimeout(loop, processConfig.comaWaitTime); - processHeartBeat(undefined, undefined, "Waiting " + processConfig.comaWaitTime / 3600000 + " hours for next execution.") - logger.persist(); - } - break; - } - } - } - - function checkLoopHealth(pLastLoop) { - - if (bot.enableCheckLoopHealth === false || global.STOP_TASK_GRACEFULLY === true) { - - logger.write(MODULE_NAME, "[WARN] run -> loop -> checkLoopHealth -> bot.enableCheckLoopHealth = " + bot.enableCheckLoopHealth); - - return; - } // This gets disabled anytime the Main Loop is shut down by any condition. - - if (bot.loopCounter <= pLastLoop + 1) { // This means that the next loop started but also stopped executing abruptally. - - let now = new Date().valueOf(); - - if (now - bot.loopStartTime > processConfig.deadWaitTime) { - - logger.write(MODULE_NAME, "[ERROR] run -> loop -> checkLoopHealth -> Dead loop found -> pLastLoop = " + pLastLoop); - console.log((new Date().toISOString() + " [ERROR] run -> loop -> checkLoopHealth -> " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " Loop # " + pad(Number(bot.loopCounter), 5) + " found dead. Resurrecting it now.")); - - logger.persist(); // We persist the logs of the failed execution. - clearTimeout(nextLoopTimeoutHandle); // We cancel the timeout in case the original loop was still running and schedulled to reexecute. - loop(); // We restart the loop so that the processing can continue. - - } else { - - console.log((new Date().toISOString() + " [WARN] run -> loop -> checkLoopHealth -> " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " Loop # " + pad(Number(bot.loopCounter), 5) + " found delayed but still alive. No action taken.")); - - } - } - } - - function shallWeStop(stopCallBack, continueCallBack) { - - try { - - /* IMPORTANT: This function is exactly the same on the 3 modules. */ - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> shallWeStop -> Entering function. "); } - - if (!global.STOP_TASK_GRACEFULLY) { - continueCallBack(); - } else { - stopCallBack(); - } - } catch (err) { - logger.write(MODULE_NAME, "[ERROR] run -> loop -> shallWeStop -> err = " + err.stack); - logger.persist(); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - return; - } - } - } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = " + err.stack); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(err); - } - } - - function processHeartBeat(processingDate, percentage, status) { - let event = { - seconds: (new Date()).getSeconds(), - processingDate: processingDate, - percentage: percentage, - status: status - } - global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Heartbeat', event) - } - - function processStopped() { - global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Stopped') - } - - } catch (err) { - parentLogger.write(MODULE_NAME, "[ERROR] run -> err = " + err.stack); - clearInterval(fixedTimeLoopIntervalHandle); - clearTimeout(nextLoopTimeoutHandle); - clearTimeout(checkLoopHealthHandle); - bot.enableCheckLoopHealth = false; - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } -}; diff --git a/IndicatorOutput.js b/IndicatorOutput.js new file mode 100644 index 000000000..1f1e62182 --- /dev/null +++ b/IndicatorOutput.js @@ -0,0 +1,168 @@ +exports.newIndicatorOutput = function newIndicatorOutput(bot, logger, UTILITIES, FILE_STORAGE) { + + const FULL_LOG = true; + const LOG_FILE_CONTENT = false; + const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000; + + const MODULE_NAME = "Indicator Bot"; + + let thisObject = { + initialize: initialize, + finalize: finalize, + start: start + }; + + let utilities = UTILITIES.newCloudUtilities(logger); + let fileStorage = FILE_STORAGE.newFileStorage(logger); + + const COMMONS = require('./Commons.js'); + let commons = COMMONS.newCommons(bot, logger, UTILITIES, FILE_STORAGE); + + return thisObject; + + function finalize() { + thisObject = undefined + utilities = undefined + fileStorage = undefined + commons = undefined + } + + function initialize(callBackFunction) { + + try { + + logger.fileName = MODULE_NAME; + logger.initialize(); + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); } + + callBackFunction(global.DEFAULT_OK_RESPONSE); + + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } + + function start(dataFiles, timeFrame, timeFrameLabel, currentDay, interExecutionMemory, callBackFunction) { + + try { + + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); } + + let products = {} + let mainDependency = {} + let processingDailyFiles + + if (currentDay !== undefined) { + processingDailyFiles = true + } else { + processingDailyFiles = false + } + + /* The first phase here is about checking that we have everything we need at the definition level. */ + let dataDependencies = bot.processNode.referenceParent.processDependencies.dataDependencies + if (commons.validateDataDependencies(dataDependencies, callBackFunction) !== true) { return } + + let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets + if (commons.validateOutputDatasets(outputDatasets, callBackFunction) !== true) { return } + + /* The second phase is about transforming the inputs into a format that can be used to apply the user defined code. */ + commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame) + + /* During the third phase, we need to generate the data of the different products this process produces an output */ + for (let i = 0; i < outputDatasets.length; i++) { + + let outputDatasetNode = outputDatasets[i] + let jsonData // Just build data as Json objects + let outputData // Data built as a result of applying user defined code and formulas at the Data Building Procedure + let singularVariableName // Name of the variable for this product + let recordDefinition // Record as defined by the user at the UI + let fileContent // Here we store the contents of the new data built just before writing it to a file. + let resultsWithIrregularPeriods // A product will have irregular periods when the User Code inserts new result records at will, in contrast with normal procedure where the platform insert one record per loop execution. + + /* + For each outputDatasetNode in our process output, we will build the information based on our input products. + */ + + recordDefinition = outputDatasetNode.referenceParent.parentNode.record + singularVariableName = outputDatasetNode.referenceParent.parentNode.config.singularVariableName + + /* Check Irregular Periods */ + + if (outputDatasetNode.referenceParent.parentNode.dataBuilding.loop.javascriptCode !== undefined) { + if (outputDatasetNode.referenceParent.parentNode.dataBuilding.loop.javascriptCode.code.indexOf('results.push') >= 0) { + resultsWithIrregularPeriods = true + } + } + + /* Build the data */ + jsonData = commons.dataBuildingProcedure( + products, + mainDependency, + recordDefinition, + outputDatasetNode.referenceParent.parentNode.dataBuilding, + singularVariableName, + outputDatasetNode.referenceParent.parentNode.config.codeName, + timeFrame, + timeFrameLabel, + resultsWithIrregularPeriods, + interExecutionMemory, + processingDailyFiles, + currentDay + ) + + /* Add the calculated properties */ + if (outputDatasetNode.referenceParent.parentNode.calculations !== undefined) { + outputData = commons.calculationsProcedure(jsonData, recordDefinition, outputDatasetNode.referenceParent.parentNode.calculations, singularVariableName, timeFrame) + } else { + outputData = jsonData + } + products[outputDatasetNode.referenceParent.parentNode.config.pluralVariableName] = outputData + } + + /*At the fourth and last phase, we will save the new information generated into files corresponding to each output outputDatasetNode.*/ + let totalFilesWritten = 0 + for (let i = 0; i < outputDatasets.length; i++) { + let outputDatasetNode = outputDatasets[i] + let outputData = products[outputDatasetNode.referenceParent.parentNode.config.pluralVariableName] + let resultsWithIrregularPeriods // A product will have irregular periods when the User Code inserts new result records at will, in contrast with normal procedure where the platform insert one record per loop execution. + let contextSummary = {} + + /* Check Irregular Periods */ + if (outputDatasetNode.referenceParent.parentNode.dataBuilding.loop.javascriptCode.code.indexOf('results.push') >= 0) { + resultsWithIrregularPeriods = true + } + + /* Simplifying the access to basic info */ + + contextSummary.dataset = outputDatasetNode.referenceParent.config.codeName + contextSummary.product = outputDatasetNode.referenceParent.parentNode.config.codeName + contextSummary.bot = outputDatasetNode.referenceParent.parentNode.parentNode.config.codeName + contextSummary.dataMine = outputDatasetNode.referenceParent.parentNode.parentNode.parentNode.config.codeName + + /* This stuff is still hardcoded and unresolved. */ + contextSummary.botVersion = { + "major": 1, + "minor": 0 + } + contextSummary.dataSetVersion = "dataSet.V1" + + let fileContent = commons.generateFileContent(outputData, outputDatasetNode.referenceParent.parentNode.record, resultsWithIrregularPeriods, processingDailyFiles, currentDay, callBackFunction) + commons.writeFile(contextSummary, fileContent, anotherFileWritten, processingDailyFiles, timeFrameLabel, currentDay, callBackFunction) + } + + + function anotherFileWritten() { + totalFilesWritten++ + if (totalFilesWritten === outputDatasets.length) { + callBackFunction(global.DEFAULT_OK_RESPONSE); + } + } + } + catch (err) { + logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + } + } +}; diff --git a/Trading/Announcements.js b/LowFrequencyTrading/Announcements.js similarity index 100% rename from Trading/Announcements.js rename to LowFrequencyTrading/Announcements.js diff --git a/Trading/Snapshots.js b/LowFrequencyTrading/Snapshots.js similarity index 100% rename from Trading/Snapshots.js rename to LowFrequencyTrading/Snapshots.js diff --git a/Trading/TradingEngine.js b/LowFrequencyTrading/TradingEngine.js similarity index 100% rename from Trading/TradingEngine.js rename to LowFrequencyTrading/TradingEngine.js diff --git a/Trading/TradingExecution.js b/LowFrequencyTrading/TradingExecution.js similarity index 100% rename from Trading/TradingExecution.js rename to LowFrequencyTrading/TradingExecution.js diff --git a/Trading/TradingBot.js b/LowFrequencyTrading/TradingOutput.js similarity index 76% rename from Trading/TradingBot.js rename to LowFrequencyTrading/TradingOutput.js index b3eacbdef..1d526efaa 100644 --- a/Trading/TradingBot.js +++ b/LowFrequencyTrading/TradingOutput.js @@ -1,4 +1,4 @@ -exports.newTradingBot = function newTradingBot(bot, logger, UTILITIES, FILE_STORAGE) { +exports.newTradingOutput = function newTradingOutput(bot, logger, UTILITIES, FILE_STORAGE) { const FULL_LOG = true const MODULE_NAME = 'Trading Bot' @@ -11,9 +11,6 @@ exports.newTradingBot = function newTradingBot(bot, logger, UTILITIES, FILE_STOR let utilities = UTILITIES.newCloudUtilities(logger) let fileStorage = FILE_STORAGE.newFileStorage(logger) - const COMMONS = require('../Commons.js') - let commons = COMMONS.newCommons(bot, logger, UTILITIES, FILE_STORAGE) - return thisObject function finalize() { @@ -35,7 +32,7 @@ exports.newTradingBot = function newTradingBot(bot, logger, UTILITIES, FILE_STOR } } - function start(multiPeriodDataFiles, timeFrame, timeFrameLabel, currentDay, simulationState, callBackFunction) { + function start(chart, timeFrame, timeFrameLabel, currentDay, simulationState, callBackFunction) { try { bot.processingDailyFiles if (timeFrame > global.dailyFilePeriods[0][0]) { @@ -43,61 +40,8 @@ exports.newTradingBot = function newTradingBot(bot, logger, UTILITIES, FILE_STOR } else { bot.processingDailyFiles = true } - let chart = {} - let mainDependency = {} - /* The first phase here is about checking that we have everything we need at the definition level. */ - let dataDependencies = bot.processNode.referenceParent.processDependencies.dataDependencies - if (commons.validateDataDependencies(dataDependencies, callBackFunction) !== true) { return } - - let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets - if (commons.validateOutputDatasets(outputDatasets, callBackFunction) !== true) { return } - - /* The second phase is about transforming the inputs into a format that can be used to apply the user defined code. */ - for (let j = 0; j < global.marketFilesPeriods.length; j++) { - let timeFrameLabel = marketFilesPeriods[j][1] - let dataFiles = multiPeriodDataFiles.get(timeFrameLabel) - let products = {} - - if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> Inflating Data Files for timeFrame = ' + timeFrameLabel) } - - if (dataFiles !== undefined) { - commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame) - - let propertyName = 'at' + timeFrameLabel.replace('-', '') - chart[propertyName] = products - } - } - - for (let j = 0; j < global.dailyFilePeriods.length; j++) { - let timeFrameLabel = global.dailyFilePeriods[j][1] - let dataFiles = multiPeriodDataFiles.get(timeFrameLabel) - let products = {} - - if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> Inflating Data Files for timeFrame = ' + timeFrameLabel) } - - if (dataFiles !== undefined) { - commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame) - - let propertyName = 'at' + timeFrameLabel.replace('-', '') - chart[propertyName] = products - } - } - - /* Single Files */ - let dataFiles = multiPeriodDataFiles.get('Single Files') - let products = {} - - if (FULL_LOG === true) { logger.write(MODULE_NAME, '[INFO] start -> Inflating Data Files from Single Files.') } - - if (dataFiles !== undefined) { - commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame) - - let propertyName = 'atAnyTimeFrame' - chart[propertyName] = products - } - - /* Simulation */ + /* Preparing everything for the Simulation */ const TRADING_SIMULATION = require('./TradingSimulation.js') let tradingSimulation = TRADING_SIMULATION.newTradingSimulation(bot, logger, UTILITIES) diff --git a/Trading/TradingProcess.js b/LowFrequencyTrading/TradingProcess.js similarity index 90% rename from Trading/TradingProcess.js rename to LowFrequencyTrading/TradingProcess.js index a8dd2e4f6..8c0c259cf 100644 --- a/Trading/TradingProcess.js +++ b/LowFrequencyTrading/TradingProcess.js @@ -1,4 +1,4 @@ -exports.newTradingProcess = function newTradingProcess(bot, logger, UTILITIES, USER_BOT_MODULE, USER_BOT_COMMONS) { +exports.newTradingProcess = function newTradingProcess(bot, logger, UTILITIES, TRADING_OUTPUT_MODULE, USER_BOT_COMMONS) { /* This Module will load all the process data dependencies from files and send them to the Trading Bot. @@ -23,7 +23,7 @@ let dataFiles = new Map(); let multiPeriodDataFiles = new Map(); - let botInstance; + let tradingOutputModule; const FILE_STORAGE = require('../FileStorage.js'); let fileStorage = FILE_STORAGE.newFileStorage(logger); @@ -41,9 +41,9 @@ dataDependenciesModule = pDataDependencies; processConfig = pProcessConfig; - let USER_BOT_MODULE = require("./TradingBot") - botInstance = USER_BOT_MODULE.newTradingBot(bot, logger, UTILITIES, FILE_STORAGE); - botInstance.initialize(callBackFunction); + let TRADING_OUTPUT_MODULE = require("./TradingOutput") + tradingOutputModule = TRADING_OUTPUT_MODULE.newTradingOutput(bot, logger, UTILITIES, FILE_STORAGE); + tradingOutputModule.initialize(callBackFunction); } catch (err) { logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); @@ -56,8 +56,8 @@ multiPeriodDataFiles = undefined statusDependencies = undefined dataDependenciesModule = undefined - botInstance.finalize() - botInstance = undefined + tradingOutputModule.finalize() + tradingOutputModule = undefined fileStorage = undefined processConfig = undefined thisObject = undefined @@ -360,7 +360,7 @@ function processDailyFiles() { let n = 0; if (currentTimeFrame) { - callTheBot() + buildCharts() return } bot.tradingProcessDate = new Date(contextVariables.lastFile.valueOf() - ONE_DAY_IN_MILISECONDS); // Go back one day to start well when we advance time at the begining of the loop. @@ -528,7 +528,7 @@ } else { n = 0; if (currentTimeFrame !== undefined) { - callTheBot(); + buildCharts(); } else { logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> timeFramesControlLoop -> Time Frame not Recognized. Can not continue."); callBackFunction(global.DEFAULT_FAIL_RESPONSE); @@ -537,16 +537,67 @@ } } - function callTheBot() { - botInstance.start( - multiPeriodDataFiles, + function buildCharts() { + const COMMONS = require('../Commons.js') + let commons = COMMONS.newCommons(bot, logger, UTILITIES, FILE_STORAGE) + + let chart = {} + let mainDependency = {} + + /* The first phase here is about checking that we have everything we need at the definition level. */ + let dataDependencies = bot.processNode.referenceParent.processDependencies.dataDependencies + if (commons.validateDataDependencies(dataDependencies, callBackFunction) !== true) { return } + + let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets + if (commons.validateOutputDatasets(outputDatasets, callBackFunction) !== true) { return } + + /* The second phase is about transforming the inputs into a format that can be used to apply the user defined code. */ + for (let j = 0; j < global.marketFilesPeriods.length; j++) { + let timeFrameLabel = marketFilesPeriods[j][1] + let dataFiles = multiPeriodDataFiles.get(timeFrameLabel) + let products = {} + + if (dataFiles !== undefined) { + commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame) + + let propertyName = 'at' + timeFrameLabel.replace('-', '') + chart[propertyName] = products + } + } + + for (let j = 0; j < global.dailyFilePeriods.length; j++) { + let timeFrameLabel = global.dailyFilePeriods[j][1] + let dataFiles = multiPeriodDataFiles.get(timeFrameLabel) + let products = {} + + if (dataFiles !== undefined) { + commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame) + + let propertyName = 'at' + timeFrameLabel.replace('-', '') + chart[propertyName] = products + } + } + + /* Single Files */ + let dataFiles = multiPeriodDataFiles.get('Single Files') + let products = {} + + if (dataFiles !== undefined) { + commons.inflateDatafiles(dataFiles, dataDependencies, products, mainDependency, timeFrame) + + let propertyName = 'atAnyTimeFrame' + chart[propertyName] = products + } + + tradingOutputModule.start( + chart, currentTimeFrame, currentTimeFrameLabel, bot.tradingProcessDate, simulationState, - onBotFinished); + onOutputGenerated); - function onBotFinished(err) { + function onOutputGenerated(err) { try { if (err.result !== global.DEFAULT_OK_RESPONSE.result) { callBackFunction(err); @@ -567,14 +618,14 @@ try { if (err.result !== global.DEFAULT_OK_RESPONSE.result) { - logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> callTheBot -> onBotFinished -> onWritten -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> buildCharts -> onOutputGenerated -> onWritten -> err = " + err.stack); callBackFunction(err); return; } writeDailyStatusReport(bot.tradingProcessDate, onDailyStatusReport); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> callTheBot -> onBotFinished -> onWritten -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> buildCharts -> onOutputGenerated -> onWritten -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } @@ -590,7 +641,7 @@ const now = new Date() if (now.valueOf() >= bot.VALUES_TO_USE.timeRange.finalDatetime.valueOf()) { const logText = "User Defined End Datetime reached @ " + now.getUTCFullYear() + "/" + (now.getUTCMonth() + 1) + "/" + now.getUTCDate() + "."; - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> callTheBot -> onBotFinished -> onMarketStatusReport -> " + logText); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processDailyFiles -> buildCharts -> onOutputGenerated -> onMarketStatusReport -> " + logText); } bot.STOP_SESSION = true callBackFunction(global.DEFAULT_OK_RESPONSE); @@ -600,7 +651,7 @@ } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> callTheBot -> onBotFinished -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> processDailyFiles -> buildCharts -> onOutputGenerated -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/Trading/TradingRecords.js b/LowFrequencyTrading/TradingRecords.js similarity index 100% rename from Trading/TradingRecords.js rename to LowFrequencyTrading/TradingRecords.js diff --git a/Trading/TradingSimulation.js b/LowFrequencyTrading/TradingSimulation.js similarity index 100% rename from Trading/TradingSimulation.js rename to LowFrequencyTrading/TradingSimulation.js diff --git a/Trading/TradingSystem.js b/LowFrequencyTrading/TradingSystem.js similarity index 100% rename from Trading/TradingSystem.js rename to LowFrequencyTrading/TradingSystem.js diff --git a/MultiPeriodDaily.js b/MultiPeriodDaily.js index 096df4c62..da6266000 100644 --- a/MultiPeriodDaily.js +++ b/MultiPeriodDaily.js @@ -18,7 +18,7 @@ let dataDependenciesModule; let dataFiles = new Map; - let botInstance; + let indicatorOutputModule; let fileStorage = FILE_STORAGE.newFileStorage(logger); @@ -42,10 +42,10 @@ dataDependenciesModule = pDataDependencies; processConfig = pProcessConfig; - let USER_BOT_MODULE = require("./IndicatorBot") + let INDICATOR_OUTPUT_MODULE = require("./IndicatorOutput") - botInstance = USER_BOT_MODULE.newIndicatorBot(bot, logger, UTILITIES, FILE_STORAGE); - botInstance.initialize(callBackFunction); + indicatorOutputModule = INDICATOR_OUTPUT_MODULE.newIndicatorOutput(bot, logger, UTILITIES, FILE_STORAGE); + indicatorOutputModule.initialize(callBackFunction); } catch (err) { logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); @@ -57,7 +57,7 @@ dataFiles = undefined statusDependencies = undefined dataDependenciesModule = undefined - botInstance = undefined + indicatorOutputModule = undefined fileStorage = undefined processConfig = undefined thisObject = undefined @@ -574,7 +574,7 @@ } else { - callTheBot(); + generateOutput(); } } @@ -584,28 +584,28 @@ } } - function callTheBot() { + function generateOutput() { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> periodsLoopBody -> generateOutput -> Entering function."); } const timeFrame = global.dailyFilePeriods[n][0]; const timeFrameLabel = global.dailyFilePeriods[n][1]; - botInstance.start( + indicatorOutputModule.start( dataFiles, timeFrame, timeFrameLabel, bot.multiPeriodDailyProcessDatetime, interExecutionMemoryArray[n], - onBotFinished); + onOutputGenerated); - function onBotFinished(err) { + function onOutputGenerated(err) { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> onBotFinished -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> periodsLoopBody -> generateOutput -> onOutputGenerated -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { @@ -617,13 +617,13 @@ periodsControlLoop(); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> onBotFinished -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> generateOutput -> onOutputGenerated -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> generateOutput -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/MultiPeriodMarket.js b/MultiPeriodMarket.js index 11bc7ae40..0464b5d30 100644 --- a/MultiPeriodMarket.js +++ b/MultiPeriodMarket.js @@ -16,7 +16,7 @@ let dataDependenciesModule; let dataFiles = new Map(); - let botInstance; + let indicatorOutputModule; let processConfig; @@ -35,10 +35,10 @@ dataDependenciesModule = pDataDependencies; processConfig = pProcessConfig; - let USER_BOT_MODULE = require("./IndicatorBot") + let INDICATOR_OUTPUT_MODULE = require("./IndicatorOutput") - botInstance = USER_BOT_MODULE.newIndicatorBot(bot, logger, UTILITIES, FILE_STORAGE); - botInstance.initialize(callBackFunction); + indicatorOutputModule = INDICATOR_OUTPUT_MODULE.newIndicatorOutput(bot, logger, UTILITIES, FILE_STORAGE); + indicatorOutputModule.initialize(callBackFunction); } catch (err) { logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); @@ -50,7 +50,7 @@ dataFiles = undefined statusDependencies = undefined dataDependenciesModule = undefined - botInstance = undefined + indicatorOutputModule = undefined processConfig = undefined thisObject = undefined } @@ -200,7 +200,7 @@ } else { - callTheBot(); + generateOutput(); } } @@ -210,28 +210,28 @@ } } - function callTheBot() { + function generateOutput() { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> periodsLoopBody -> generateOutput -> Entering function."); } const timeFrame = global.marketFilesPeriods[n][0]; const timeFrameLabel = global.marketFilesPeriods[n][1]; - botInstance.start( + indicatorOutputModule.start( dataFiles, timeFrame, timeFrameLabel, undefined, undefined, - onBotFinished); + onOutputGenerated); - function onBotFinished(err) { + function onOutputGenerated(err) { try { - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> onBotFinished -> Entering function."); } + if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> processTimeFrames -> periodsLoopBody -> generateOutput -> onOutputGenerated -> Entering function."); } if (err.result !== global.DEFAULT_OK_RESPONSE.result) { @@ -242,13 +242,13 @@ periodsControlLoop(); } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> onBotFinished -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> generateOutput -> onOutputGenerated -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } } catch (err) { - logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> callTheBot -> err = " + err.stack); + logger.write(MODULE_NAME, "[ERROR] start -> processTimeFrames -> periodsLoopBody -> generateOutput -> err = " + err.stack); callBackFunction(global.DEFAULT_FAIL_RESPONSE); } } diff --git a/Root.js b/Root.js index f3411d1ba..329f2eda7 100644 --- a/Root.js +++ b/Root.js @@ -132,9 +132,9 @@ /* Process Loops Declarations. */ - const INDICATOR_BOT_MAIN_LOOP_MODULE = require('./IndicatorBotProcessMainLoop'); - const SENSOR_BOT_MAIN_LOOP_MODULE = require('./SensorBotProcessMainLoop'); - const TRADING_ENGINE_MAIN_LOOP_MODULE = require('./TradingBotProcessMainLoop'); + const INDICATOR_BOT_MODULE = require('./IndicatorBot'); + const SENSOR_BOT = require('./SensorBot'); + const TRADING_BOT_MODULE = require('./TradingBot'); let botConfig; let processInstance = global.TASK_NODE.bot.processes[processIndex] @@ -144,7 +144,7 @@ processInstance.referenceParent.config.framework !== undefined && (processInstance.referenceParent.config.framework.name === 'Multi-Period-Market' || processInstance.referenceParent.config.framework.name === 'Multi-Period-Daily' || - processInstance.referenceParent.config.framework.name === 'Trading-Process') + processInstance.referenceParent.config.framework.name === 'Low-Frequency-Trading-Process') ) { botConfig = processInstance.referenceParent.parentNode.config botConfig.definedByUI = true @@ -396,14 +396,14 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runSensorBot -> Entering function."); } - let extractionBotMainLoop = SENSOR_BOT_MAIN_LOOP_MODULE.newSensorBotProcessMainLoop(pBotConfig, logger); - extractionBotMainLoop.initialize(pProcessConfig, onInitializeReady); + let sensorBot = SENSOR_BOT.newSensorBot(pBotConfig, logger); + sensorBot.initialize(pProcessConfig, onInitializeReady); function onInitializeReady(err) { if (err.result === global.DEFAULT_OK_RESPONSE.result) { - extractionBotMainLoop.run(whenRunFinishes); + sensorBot.run(whenRunFinishes); function whenRunFinishes(err) { @@ -461,14 +461,14 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runIndicatorBot -> Entering function."); } - let indicatorBotMainLoop = INDICATOR_BOT_MAIN_LOOP_MODULE.newIndicatorBotProcessMainLoop(pBotConfig, logger); - indicatorBotMainLoop.initialize(pProcessConfig, onInitializeReady); + let indicatorBot = INDICATOR_BOT_MODULE.newIndicatorBot(pBotConfig, logger); + indicatorBot.initialize(pProcessConfig, onInitializeReady); function onInitializeReady(err) { if (err.result === global.DEFAULT_OK_RESPONSE.result) { - indicatorBotMainLoop.run(whenRunFinishes); + indicatorBot.run(whenRunFinishes); function whenRunFinishes(err) { @@ -524,14 +524,14 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> bootingBot -> runTradingBot -> Entering function."); } - let tradingBotMainLoop = TRADING_ENGINE_MAIN_LOOP_MODULE.newTradingBotProcessMainLoop(pBotConfig, logger); - tradingBotMainLoop.initialize(pProcessConfig, onInitializeReady); + let tradingBot = TRADING_BOT_MODULE.newTradingBot(pBotConfig, logger); + tradingBot.initialize(pProcessConfig, onInitializeReady); function onInitializeReady(err) { if (err.result === global.DEFAULT_OK_RESPONSE.result) { - tradingBotMainLoop.run(whenRunFinishes); + tradingBot.run(whenRunFinishes); function whenRunFinishes(err) { diff --git a/SensorBotProcessMainLoop.js b/SensorBot.js similarity index 99% rename from SensorBotProcessMainLoop.js rename to SensorBot.js index 5502fc340..a40fc6203 100644 --- a/SensorBotProcessMainLoop.js +++ b/SensorBot.js @@ -1,4 +1,4 @@ -exports.newSensorBotProcessMainLoop = function newSensorBotProcessMainLoop(bot, parentLogger) { +exports.newSensorBot = function newSensorBot(bot, parentLogger) { const ROOT_DIR = './'; @@ -825,6 +825,16 @@ global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Heartbeat', event) } + function processError(node, errorMessage) { + let event = { + nodeName: node.name, + nodeType: node.type, + nodeId: node.id, + errorMessage: errorMessage + } + global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Error', event) + } + function processStopped() { global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Stopped') } diff --git a/TradingBotProcessMainLoop.js b/TradingBot.js similarity index 99% rename from TradingBotProcessMainLoop.js rename to TradingBot.js index c2dbd8deb..0431e9bc3 100644 --- a/TradingBotProcessMainLoop.js +++ b/TradingBot.js @@ -1,4 +1,4 @@ -exports.newTradingBotProcessMainLoop = function newTradingBotProcessMainLoop(bot, parentLogger) { +exports.newTradingBot = function newTradingBot(bot, parentLogger) { const ROOT_DIR = './'; @@ -8,7 +8,7 @@ let USER_BOT_MODULE; let USER_BOT_COMMONS; - const TRADING_PROCESS_MODULE = require(ROOT_DIR + '/Trading/TradingProcess.js'); + const TRADING_PROCESS_MODULE = require(ROOT_DIR + '/LowFrequencyTrading/TradingProcess.js'); const FILE_STORAGE = require('./FileStorage.js'); const SESSION = require(ROOT_DIR + 'Session'); @@ -400,7 +400,7 @@ case global.DEFAULT_OK_RESPONSE.result: { if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> initializeDataDependencies -> onInizialized -> Execution finished well."); } switch (processConfig.framework.name) { - case 'Trading-Process': { + case 'Low-Frequency-Trading-Process': { processFramework = TRADING_PROCESS_MODULE.newTradingProcess(bot, logger, UTILITIES, USER_BOT_MODULE, USER_BOT_COMMONS); intitializeProcessFramework(); break;