Beta 6 without Execution

This commit is contained in:
Luis Fernando Molina committed 2020-07-06 15:43:34 +02:00
1 parent 4033d4d07f
commit d40b985f5e
123 files changed
+8114 -12392

No files matched your search

+760 -122
View File
@@ -1,167 +1,805 @@
exports.newIndicatorBot = function newIndicatorBot(bot, logger, UTILITIES, FILE_STORAGE) {
const FULL_LOG = true;
const LOG_FILE_CONTENT = false;
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
exports.newIndicatorBot = function newIndicatorBot(bot, parentLogger) {
const MODULE_NAME = "Indicator Bot";
const FULL_LOG = true;
let USER_BOT_MODULE;
let COMMONS_MODULE;
const MULTI_PERIOD_MARKET = require(global.ROOT_DIR + 'MultiPeriodMarket');
const MULTI_PERIOD_DAILY = require(global.ROOT_DIR + 'MultiPeriodDaily');
const FILE_STORAGE = require('./FileStorage.js');
let fileStorage = FILE_STORAGE.newFileStorage(parentLogger);
const DEBUG_MODULE = require(global.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 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 {
processConfig = pProcessConfig;
logger.fileName = MODULE_NAME;
logger.initialize();
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
}
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
/* 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"
callBackFunction(global.DEFAULT_OK_RESPONSE);
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 {
let fixedTimeLoopIntervalHandle;
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); }
/* Errors sent to the UI */
bot.processError = processError
let products = {}
let mainDependency = {}
let processingDailyFiles
/* Heartbeats sent to the UI */
bot.processHeartBeat = processHeartBeat
if (currentDay !== undefined) {
processingDailyFiles = true
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() {
try {
function pad(str, max) {
str = str.toString();
return str.length < max ? pad(" " + str, max) : str;
}
let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets
if (commons.validateOutputDatasets(outputDatasets, callBackFunction) !== true) { return }
/* 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();
/* 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)
bot.loopCounter++;
bot.loopStartTime = new Date().valueOf();
/* 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++) {
/* We tell the UI that we are running. */
processHeartBeat()
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.
/* We define here all the modules that the rest of the infraestructure, including the bots themselves can consume. */
const UTILITIES = require(global.ROOT_DIR + 'CloudUtilities');
const STATUS_REPORT = require(global.ROOT_DIR + 'StatusReport');
const STATUS_DEPENDENCIES = require(global.ROOT_DIR + 'StatusDependencies');
const DATA_DEPENDENCIES = require(global.ROOT_DIR + 'DataDependencies');
const DATA_SET = require(global.ROOT_DIR + 'DataSet');
const PROCESS_EXECUTION_EVENTS = require(global.ROOT_DIR + 'ProcessExecutionEvents');
const PROCESS_OUTPUT = require(global.ROOT_DIR + 'ProcessOutput');
/*
For each outputDatasetNode in our process output, we will build the information based on our input products.
*/
/* 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.
recordDefinition = outputDatasetNode.referenceParent.parentNode.record
singularVariableName = outputDatasetNode.referenceParent.parentNode.code.singularVariableName
/* 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))
/* Check Irregular Periods */
/* 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;
if (outputDatasetNode.referenceParent.parentNode.dataBuilding.loop.javascriptCode !== undefined) {
if (outputDatasetNode.referenceParent.parentNode.dataBuilding.loop.javascriptCode.code.indexOf('results.push') >= 0) {
resultsWithIrregularPeriods = true
let nextWaitTime;
initializeProcessExecutionEvents();
function initializeProcessExecutionEvents() {
try {
processExecutionEvents = PROCESS_EXECUTION_EVENTS.newProcessExecutionEvents(bot, logger)
processExecutionEvents.initialize(onInizialized);
function onInizialized(err) {
try {
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.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> onInizialized -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeProcessExecutionEvents -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function startProcessExecutionEvents() {
try {
processExecutionEvents.start(onStarted);
function onStarted(err) {
try {
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.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> onStarted -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessExecutionEvents -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function initializeStatusDependencies() {
try {
statusDependencies = STATUS_DEPENDENCIES.newStatusDependencies(bot, logger, STATUS_REPORT, UTILITIES, PROCESS_OUTPUT);
statusDependencies.initialize(onInizialized);
function onInizialized(err) {
try {
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.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> onInizialized -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeStatusDependencies -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function initializeDataDependencies() {
try {
dataDependencies = DATA_DEPENDENCIES.newDataDependencies(bot, logger, DATA_SET);
dataDependencies.initialize(onInizialized);
function onInizialized(err) {
try {
switch (err.result) {
case global.DEFAULT_OK_RESPONSE.result: {
/* 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);
global.unexpectedError = err.message
processStopped()
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.");
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> onInizialized -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeDataDependencies -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function initializeUserBot() {
try {
usertBot = USER_BOT_MODULE.newUserBot(bot, logger, COMMONS_MODULE, UTILITIES, FILE_STORAGE);
usertBot.initialize(statusDependencies, onInizialized);
function onInizialized(err) {
try {
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.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> onInizialized -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> initializeUserBot -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function startUserBot() {
try {
usertBot.start(onFinished);
function onFinished(err) {
try {
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.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> onFinished -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startUserBot -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function intitializeProcessFramework() {
try {
processFramework.initialize(processConfig, statusDependencies, dataDependencies, onInizialized);
function onInizialized(err) {
try {
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.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> onInizialized -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> intitializeProcessFramework -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function startProcessFramework() {
try {
processFramework.start(onFinished);
function onFinished(err) {
try {
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.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> onFinished -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> startProcessFramework -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function finishProcessExecutionEvents() {
try {
processExecutionEvents.finish(onFinished);
function onFinished(err) {
try {
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.
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> Operation Failed. Aborting the process.");
global.unexpectedError = err.message
processStopped()
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);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> onFinished -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> finishProcessExecutionEvents -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
function loopControl(nextWaitTime) {
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 -> Stopping the Loop Gracefully. See you next time!"); }
processStopped()
return;
}
function onContinue() {
/* 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."); }
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."); }
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 shallWeStop(stopCallBack, continueCallBack) {
try {
/* IMPORTANT: This function is exactly the same on the 3 modules. */
if (!global.STOP_TASK_GRACEFULLY) {
continueCallBack();
} else {
stopCallBack();
}
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] run -> loop -> shallWeStop -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
} catch (err) {
parentLogger.write(MODULE_NAME, "[ERROR] run -> loop -> err = " + err.stack);
global.unexpectedError = err.message
processStopped()
return
}
}
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
if (node !== undefined) {
event = {
nodeName: node.name,
nodeType: node.type,
nodeId: node.id,
errorMessage: errorMessage
}
} else {
event = {
errorMessage: errorMessage
}
}
global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Error', event)
}
/* Build the data */
jsonData = commons.dataBuildingProcedure(
products,
mainDependency,
recordDefinition,
outputDatasetNode.referenceParent.parentNode.dataBuilding,
singularVariableName,
outputDatasetNode.referenceParent.parentNode.code.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)
function processStopped() {
if (global.unexpectedError !== undefined) {
processError(undefined, "An unexpected error caused the Process to stop.")
} else {
outputData = jsonData
global.EVENT_SERVER_CLIENT.raiseEvent(bot.processKey, 'Stopped')
}
products[outputDatasetNode.referenceParent.parentNode.code.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.code.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.code.codeName
contextSummary.product = outputDatasetNode.referenceParent.parentNode.code.codeName
contextSummary.bot = outputDatasetNode.referenceParent.parentNode.parentNode.code.codeName
contextSummary.dataMine = outputDatasetNode.referenceParent.parentNode.parentNode.parentNode.code.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);
logger.persist();
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
if (global.unexpectedError !== undefined) {
callBackFunction(global.DEFAULT_FAIL_RESPONSE)
} else {
callBackFunction(global.DEFAULT_OK_RESPONSE)
}
}
}
catch (err) {
logger.write(MODULE_NAME, "[ERROR] start -> err = " + err.stack);
} catch (err) {
parentLogger.write(MODULE_NAME, "[ERROR] run -> err = " + err.stack);
clearInterval(fixedTimeLoopIntervalHandle);
clearTimeout(nextLoopTimeoutHandle);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}