diff --git a/IndicatorBotCommons.js b/IndicatorBotCommons.js index d1ae58093..959c6deda 100644 --- a/IndicatorBotCommons.js +++ b/IndicatorBotCommons.js @@ -10,10 +10,7 @@ let thisObject = { jsonifyDataFile: jsonifyDataFile, calculationsProcedure: calculationsProcedure, - buildStandardChannels: buildStandardChannels, - buildSubChannels: buildSubChannels, - buildStandardSubChannels: buildStandardSubChannels, - buildRecords: buildRecords + dataBuildingProcedure: dataBuildingProcedure }; return thisObject; @@ -54,26 +51,39 @@ timePeriod: timePeriod, ONE_DAY_IN_MILISECONDS: ONE_DAY_IN_MILISECONDS } - let variable = {} // This is the structure where the user will define its own variables that will be shared amond different code blocks and formulas. - let resultingArray = [] + let variable = {} // This is the structure where the user will define its own variables that will be shared across different code blocks and formulas. + let results = [] /* This is Initialization Code */ if (calculationsProcedure.initialization !== undefined) { if (calculationsProcedure.initialization.code !== undefined) { - eval(calculationsProcedure.initialization.code.code) + try { + eval(calculationsProcedure.initialization.code.code) + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> initialization -> Error executing User Code. Error = " + err.stack) + logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> initialization -> Error executing User Code. Code = " + calculationsProcedure.initialization.code.code); + throw("Error Executing User Code.") + } } } /* This is Initialization Code */ if (calculationsProcedure.loop !== undefined) { if (calculationsProcedure.loop.code !== undefined) { - for (let i = 0; i < jsonArray.length; i++) { + for (let index = 0; index < jsonArray.length; index++) { - let indicator = {} - indicator[variableName] = jsonArray[i] + let product = {} + product[variableName] = jsonArray[index] /* This is Loop Code */ - eval(calculationsProcedure.loop.code.code) + try { + eval(calculationsProcedure.loop.code.code) + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> Error executing User Code. Error = " + err.stack) + logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> Error executing User Code. product = " + JSON.stringify(product)) + logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> Error executing User Code. Code = " + calculationsProcedure.loop.code.code); + throw ("Error Executing User Code.") + } /* For each calculated property we apply its formula*/ for (let j = 0; j < recordDefinition.properties.length; j++) { @@ -81,8 +91,16 @@ if (property.code.isCalculated === true) { if (property.formula !== undefined) { if (property.formula.code !== undefined) { - let newValue = eval(property.formula.code) - let currentRecord = indicator[variableName] + let newValue + try { + newvalue = eval(property.formula.code) + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. Error = " + err.stack) + logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. product = " + JSON.stringify(product)) + logger.write(MODULE_NAME, "[ERROR] calculationsProcedure -> loop -> formula -> Error executing User Code. Code = " + property.formula.code); + throw ("Error Executing User Code.") + } + let currentRecord = product[variableName] currentRecord[property.code.codeName] = newValue } } @@ -90,440 +108,96 @@ } /* Adding the new element to the resulting array */ - resultingArray.push(indicator.bollingerBand); + results.push(product[variableName]); } } } - return resultingArray + return results } - function addCalculatedProperties(dependencyArray, variableName, timePeriod) { + function dataBuildingProcedure(products, mainDependency, recordDefinition, dataBuildingProcedure, variableName, timePeriod) { - let dependecyArray = [] + /* + This function has as an input the products object, with all the information + of all products calculated so far by the process. Based on that information + the function will evaluate user supplied code and formulas in order to build + a new set of information. + */ + + let system = { // These are the available system variables to be used in User Code and Formulas + timePeriod: timePeriod, + ONE_DAY_IN_MILISECONDS: ONE_DAY_IN_MILISECONDS + } + let variable = {} // This is the structure where the user will define its own variables that will be shared across different code blocks and formulas. + let results = [] /* This is Initialization Code */ - let lastMovingAverage = 0; - const SIDE_TOLERANCE = 0.5 * timePeriod / ONE_DAY_IN_MILISECONDS; - const SMALL_SLOPE = 1.0 * timePeriod / ONE_DAY_IN_MILISECONDS; - const MEDIUM_SLOPE = 2.0 * timePeriod / ONE_DAY_IN_MILISECONDS; - const HIGH_SLOPE = 4.0 * timePeriod / ONE_DAY_IN_MILISECONDS; + if (dataBuildingProcedure.initialization !== undefined) { + if (dataBuildingProcedure.initialization.code !== undefined) { + try { + eval(dataBuildingProcedure.initialization.code.code) + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> initialization -> Error executing User Code. Error = " + err.stack) + logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> initialization -> Error executing User Code. Code = " + dataBuildingProcedure.initialization.code.code); + throw ("Error Executing User Code.") + } + } + } + /* This is Initialization Code */ + if (dataBuildingProcedure.loop !== undefined) { + if (dataBuildingProcedure.loop.code !== undefined) { + for (let index = 0; index < mainDependency.length; index++) { - for (let i = 0; i < dataFile.length; i++) { + let record = { + previous: mainDependency[index-1], + current: mainDependency[index], + next: mainDependency[index+1] + } - let indicator = {} - indicator[variableName] = dataFile[i] + let product = {} + product[variableName] = {} - /* This is Add Properties Code */ - if (lastMovingAverage > indicator.bollingerBand.movingAverage) { indicator.bollingerBand.direction = 'Down'; } - if (lastMovingAverage < indicator.bollingerBand.movingAverage) { indicator.bollingerBand.direction = 'Up'; } - if (lastMovingAverage === indicator.bollingerBand.movingAverage) { indicator.bollingerBand.direction = 'Side'; } + /* This is Loop Code */ + try { + eval(dataBuildingProcedure.loop.code.code) + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> Error executing User Code. Error = " + err.stack) + logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> Error executing User Code. product = " + JSON.stringify(product)) + logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> Error executing User Code. Code = " + dataBuildingProcedure.loop.code.code); + throw ("Error Executing User Code.") + } - let delta = Math.abs(indicator.bollingerBand.movingAverage - lastMovingAverage); - - indicator.bollingerBand.slope = 'Extreme'; - if (delta < indicator.bollingerBand.movingAverage * HIGH_SLOPE / 100) { indicator.bollingerBand.slope = 'Steep'; } - if (delta < indicator.bollingerBand.movingAverage * MEDIUM_SLOPE / 100) { indicator.bollingerBand.slope = 'Medium'; } - if (delta < indicator.bollingerBand.movingAverage * SMALL_SLOPE / 100) { indicator.bollingerBand.slope = 'Gentle'; } - if (delta < indicator.bollingerBand.movingAverage * SIDE_TOLERANCE / 100) { indicator.bollingerBand.slope = 'Side'; } - - lastMovingAverage = indicator.bollingerBand.movingAverage; - /* This is Add Properties Code */ - - dependecyArray.push(indicator.bollingerBand); - } - - return dependecyArray - } - - function buildRecords(dataDependency, recordDefinition) { - let records = [] - - /* Initialization Code */ - let period = 1 - /* Initialization Code */ - - for (let i = 0; i < dataDependency.bollinerBands.length; i++) { - - /* Calculations Code*/ - if (i === 0) {continue} - let currentBand = dataDependency.bollinerBands[i]; - let previousBand = dataDependency.bollinerBands[i - 1]; - - if (currentBand.direction === previousBand.direction) { - period++ - } else { - period = 1 - } - /* Calculations Code*/ - - let record = { - begin: currentBand.begin, /* Property Formula Code */ - end: currentBand.end, /* Property Formula Code */ - direction: currentBand.direction, /* Property Formula Code */ - period: period /* Property Formula Code */ - }; - records.push(record) - } - return records - } - - - function buildBandsArray(dataFile, bands, timePeriod, callBackFunction) { - - try { - - let lastMovingAverage = 0; - const SIDE_TOLERANCE = 0.5 * timePeriod / ONE_DAY_IN_MILISECONDS; - const SMALL_SLOPE = 1.0 * timePeriod / ONE_DAY_IN_MILISECONDS; - const MEDIUM_SLOPE = 2.0 * timePeriod / ONE_DAY_IN_MILISECONDS; - const HIGH_SLOPE = 4.0 * timePeriod / ONE_DAY_IN_MILISECONDS; - - for (let i = 0; i < dataFile.length; i++) { - - let band = { - begin: undefined, - end: undefined, - movingAverage: 10000000000000, - standardDeviation: 0, - deviation: undefined - }; - - band.begin = dataFile[i][0]; - band.end = dataFile[i][1]; - - band.movingAverage = dataFile[i][2]; - band.standardDeviation = dataFile[i][3]; - band.deviation = dataFile[i][4]; - - if (lastMovingAverage > band.movingAverage) { band.direction = 'Down'; } - if (lastMovingAverage < band.movingAverage) { band.direction = 'Up'; } - if (lastMovingAverage === band.movingAverage) { band.direction = 'Side'; } - - let delta = Math.abs(band.movingAverage - lastMovingAverage); - - band.slope = 'Extreme'; - if (delta < band.movingAverage * HIGH_SLOPE / 100) { band.slope = 'Steep'; } - if (delta < band.movingAverage * MEDIUM_SLOPE / 100) { band.slope = 'Medium'; } - if (delta < band.movingAverage * SMALL_SLOPE / 100) { band.slope = 'Gentle'; } - if (delta < band.movingAverage * SIDE_TOLERANCE / 100) { band.slope = 'Side'; } - - bands.push(band); - - lastMovingAverage = band.movingAverage; - } - } - catch (err) { - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - function buildChannels(bands, channels, callBackFunction) { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildChannels -> Entering function."); } - - try { - - let channel; - - for (let i = 0; i < bands.length; i++) { - - let currentBand = bands[i]; - let nextBand; - - if (i < bands.length - 1) { - nextBand = bands[i + 1]; - - if ( - currentBand.direction === nextBand.direction) { - - if (channel === undefined) { - - channel = { - begin: undefined, - end: undefined, - direction: undefined, - period: 0, - firstMovingAverage: 0, - lastMovingAverage: 0, - firstDeviation: 0, - lastDeviation: 0 - }; - - channel.direction = currentBand.direction; - channel.period = 2; - - channel.begin = currentBand.begin; - channel.end = nextBand.end; - - channel.firstMovingAverage = currentBand.movingAverage; - channel.lastMovingAverage = nextBand.movingAverage; - - channel.firstDeviation = currentBand.deviation; - channel.lastDeviation = nextBand.deviation; - - } else { - - channel.period++; - channel.end = nextBand.end; - channel.lastMovingAverage = nextBand.movingAverage; - channel.lastDeviation = nextBand.deviation; - - } - } else { - - if (channel !== undefined) { - channels.push(channel); - channel = undefined; - } else { - /* The channel has only one period */ - - channel = {}; - - channel.direction = currentBand.direction; - channel.period = 1; - - channel.begin = currentBand.begin; - channel.end = currentBand.end; - - channel.firstMovingAverage = currentBand.movingAverage; - channel.lastMovingAverage = currentBand.movingAverage; - - channel.firstDeviation = currentBand.deviation; - channel.lastDeviation = currentBand.deviation; - - channels.push(channel); - channel = undefined; + /* For each non-calculated property we apply its formula*/ + for (let j = 0; j < recordDefinition.properties.length; j++) { + let property = recordDefinition.properties[j] + if (property.code.isCalculated !== true) { + if (property.formula !== undefined) { + if (property.formula.code !== undefined) { + let newValue + try { + newvalue = eval(property.formula.code) + } catch (err) { + logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> formula -> Error executing User Code. Error = " + err.stack) + logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> formula -> Error executing User Code. product = " + JSON.stringify(product)) + logger.write(MODULE_NAME, "[ERROR] dataBuildingProcedure -> loop -> formula -> Error executing User Code. Code = " + property.formula.code); + throw ("Error Executing User Code.") + } + let currentRecord = product[variableName] + currentRecord[property.code.codeName] = newValue + } + } } } - } else { - if (channel !== undefined) { - channel.period++; - channel.end = currentBand.end; - channel.lastMovingAverage = currentBand.movingAverage; - channel.lastDeviation = currentBand.deviation; - channels.push(channel); - channel = undefined; - } else { - /* The channel has only one period */ - channel = {}; - - channel.direction = currentBand.direction; - channel.period = 1; - - channel.begin = currentBand.begin; - channel.end = currentBand.end; - - channel.firstMovingAverage = currentBand.movingAverage; - channel.lastMovingAverage = currentBand.movingAverage; - - channel.firstDeviation = currentBand.deviation; - channel.lastDeviation = currentBand.deviation; - - channels.push(channel); - channel = undefined; + /* If within the code the new data structure was not yet pushed to the results array, we do it */ + if (dataBuildingProcedure.loop.code.code.indexOf('results.push') < 0) { + /* Adding the new element to the resulting array */ + results.push(product[variableName]); } } } } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] buildChannels -> err = " + err.stack); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - function buildStandardChannels(bands, standardChannels, callBackFunction) { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildStandardChannels -> Entering function."); } - - try { - - let period = 1 - - for (let i = 1; i < bands.length; i++) { - - let channel; - let currentBand = bands[i]; - let previousBand = bands[i - 1]; - - if (currentBand.direction === previousBand.direction) { - period++ - } else { - period = 1 - } - - channel = { - begin: currentBand.begin, - end: currentBand.end, - direction: currentBand.direction, - period: period - }; - - standardChannels.push(channel) - } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] buildStandardChannels -> err = " + err.stack); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - function buildSubChannels(bands, subChannels, callBackFunction) { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildSubChannels -> Entering function."); } - - try { - - let channel; - - for (let i = 0; i < bands.length; i++) { - - let currentBand = bands[i]; - let nextBand; - - if (i < bands.length - 1) { - nextBand = bands[i + 1]; - - if ( - currentBand.direction === nextBand.direction && - currentBand.slope === nextBand.slope) { - - if (channel === undefined) { - - channel = { - begin: undefined, - end: undefined, - direction: undefined, - slope: undefined, - period: 0, - firstMovingAverage: 0, - lastMovingAverage: 0, - firstDeviation: 0, - lastDeviation: 0 - }; - - channel.direction = currentBand.direction; - channel.slope = currentBand.slope; - channel.period = 2; - - channel.begin = currentBand.begin; - channel.end = nextBand.end; - - channel.firstMovingAverage = currentBand.movingAverage; - channel.lastMovingAverage = nextBand.movingAverage; - - channel.firstDeviation = currentBand.deviation; - channel.lastDeviation = nextBand.deviation; - - } else { - - channel.period++; - channel.end = nextBand.end; - channel.lastMovingAverage = nextBand.movingAverage; - channel.lastDeviation = nextBand.deviation; - - } - } else { - - if (channel !== undefined) { - subChannels.push(channel); - channel = undefined; - } else { - /* The channel has only one period */ - - channel = {}; - - channel.direction = currentBand.direction; - channel.slope = currentBand.slope; - channel.period = 1; - - channel.begin = currentBand.begin; - channel.end = currentBand.end; - - channel.firstMovingAverage = currentBand.movingAverage; - channel.lastMovingAverage = currentBand.movingAverage; - - channel.firstDeviation = currentBand.deviation; - channel.lastDeviation = currentBand.deviation; - - subChannels.push(channel); - channel = undefined; - } - } - - } else { - if (channel !== undefined) { - channel.period++; - channel.end = currentBand.end; - channel.lastMovingAverage = currentBand.movingAverage; - channel.lastDeviation = currentBand.deviation; - subChannels.push(channel); - channel = undefined; - } else { - /* The channel has only one period */ - - channel = {}; - - channel.direction = currentBand.direction; - channel.slope = currentBand.slope; - channel.period = 1; - - channel.begin = currentBand.begin; - channel.end = currentBand.end; - - channel.firstMovingAverage = currentBand.movingAverage; - channel.lastMovingAverage = currentBand.movingAverage; - - channel.firstDeviation = currentBand.deviation; - channel.lastDeviation = currentBand.deviation; - - subChannels.push(channel); - channel = undefined; - } - } - } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] buildSubChannels -> err = " + err.stack); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } - } - - function buildStandardSubChannels(bands, standardSubChannels, callBackFunction) { - - if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] buildStandardSubChannels -> Entering function."); } - - try { - - let period = 1 - - for (let i = 1; i < bands.length; i++) { - - let channel; - let currentBand = bands[i]; - let previousBand = bands[i - 1]; - - if (currentBand.direction === previousBand.direction && currentBand.slope === previousBand.slope) { - period++ - } else { - period = 1 - } - - channel = { - begin: currentBand.begin, - end: currentBand.end, - direction: currentBand.direction, - slope: currentBand.slope, - period: period - }; - - standardSubChannels.push(channel) - } - } - catch (err) { - logger.write(MODULE_NAME, "[ERROR] buildStandardSubChannels -> err = " + err.stack); - callBackFunction(global.DEFAULT_FAIL_RESPONSE); - } + return results } }; diff --git a/IndicatorBotMarket.js b/IndicatorBotMarket.js index 57fe4073e..1f6c44456 100644 --- a/IndicatorBotMarket.js +++ b/IndicatorBotMarket.js @@ -48,6 +48,8 @@ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> Entering function."); } let market = global.MARKET; + let products = {} + let mainDependency let dataDependencies = bot.processNode.referenceParent.processDependencies.dataDependencies for (let i = 0; i < dataDependencies.length; i++) { @@ -56,7 +58,7 @@ let dataFile = dataFiles[i] let jsonData // Datafile converted into Json objects let inputData // Includes calculated properties - let variableName // name of the variable for this product + let singularVariableName // name of the variable for this product let recordDefinition /* @@ -66,8 +68,13 @@ */ /* Basic validations to see if we have everything we need. */ - if (dataset.parentNode.code.variableName === undefined) { - logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode)); + if (dataset.parentNode.code.singularVariableName === undefined) { + logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Single Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode)); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return + } + if (dataset.parentNode.code.pluralVariableName === undefined) { + logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Plural Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode)); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } @@ -76,8 +83,52 @@ callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } - if (dataset.parentNode.calculations === undefined) { - logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Calculations Procedure. Product Definition = " + JSON.stringify(dataset.parentNode)); + + recordDefinition = dataset.parentNode.record + singularVariableName = dataset.parentNode.code.singularVariableName + /* Transform the raw data into JSON objects */ + jsonData = commons.jsonifyDataFile(dataFile, recordDefinition) + /* Add the calculated properties */ + if (dataset.parentNode.calculations !== undefined) { + inputData = commons.calculationsProcedure(jsonData, recordDefinition, dataset.parentNode.calculations, singularVariableName, timePeriod) + } else { + inputData = jsonData + } + products[dataset.parentNode.code.pluralVariableName] = inputData + + /* The main dependency is defined as the first dependency processed. */ + if (mainDependency === undefined) { + mainDependency = inputData + } + } + + /* During the next phase, we need to generate the data of the different products this process produces an output */ + let outputDatasets = bot.processNode.referenceParent.processOutput.outputDatasets + for (let i = 0; i < outputDatasets.length; i++) { + + let dataset = outputDatasets[i].referenceParent + 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 + + /* + For each dataset in our process output, we will build the information based on our input products. + */ + + /* Basic validations to see if we have everything we need. */ + if (dataset.parentNode.code.singularVariableName === undefined) { + logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Single Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode)); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return + } + if (dataset.parentNode.code.pluralVariableName === undefined) { + logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Plural Variable Name defined. Product Definition = " + JSON.stringify(dataset.parentNode)); + callBackFunction(global.DEFAULT_FAIL_RESPONSE); + return + } + if (dataset.parentNode.record === undefined) { + logger.write(MODULE_NAME, "[ERROR] start -> Product Definition without a Record Definition. Product Definition = " + JSON.stringify(dataset.parentNode)); callBackFunction(global.DEFAULT_FAIL_RESPONSE); return } @@ -88,16 +139,22 @@ } recordDefinition = dataset.parentNode.record - variableName = dataset.parentNode.code.variableName - /* Transform the raw data into JSON objects */ - jsonData = commons.jsonifyDataFile(dataFile, recordDefinition) + singularVariableName = dataset.parentNode.code.singularVariableName + + /* Build the data */ + jsonData = commons.dataBuildingProcedure(products, mainDependency, recordDefinition, dataset.parentNode.dataBuilding, singularVariableName, timePeriod) + /* Add the calculated properties */ if (dataset.parentNode.calculations !== undefined) { - inputData = commons.calculationsProcedure(jsonData, recordDefinition, dataset.parentNode.calculations, variableName, timePeriod) + outputData = commons.calculationsProcedure(jsonData, recordDefinition, dataset.parentNode.calculations, singularVariableName, timePeriod) + } else { + outputData = jsonData } + products[dataset.parentNode.code.pluralVariableName] = outputData } - /* During the next phase, we need to generate the data of the different products this process produces an output */ + + diff --git a/server.js b/server.js index 7713e3b90..9697386e5 100644 --- a/server.js +++ b/server.js @@ -53,46 +53,6 @@ process.on('exit', function (code) { console.log('[INFO] Task Server -> server -> process.on.exit -> About to exit -> code = ' + code) }) -/* - -We read the first string sent as an argument when the process was created by the Task Manager. Ther we will find the information of the identity -of this Task and know exactly what to run within this server instance. - -*/ -global.TASK_NODE = process.argv[2] - -if (global.TASK_NODE !== undefined) { - - try { - global.TASK_NODE = JSON.parse(global.TASK_NODE) - console.log('[INFO] Task Server -> server -> global.TASK_NODE = ' + JSON.stringify(global.TASK_NODE)) - } catch (err) { - console.log('[ERROR] Task Server -> server -> global.TASK_NODE -> ' + err.stack) - } - -} -else { // I use this section to debug in standalone mode. - global.TASK_NODE = { "type": "Task", "name": "Generates Bollinger Channels & Sub-Channels", "bot": { "type": "Indicator Bot Instance", "name": "Paula", "code": { "team": "AAMasters", "bot": "AAPaula", "repo": "AAPaula-Indicator-Bot" }, "processes": [{ "type": "Process Instance", "subType": "Indicator Process Instance", "name": "Market", "code": { "process": "Multi-Period-Market" }, "id": "6ddd81e2-d6db-4814-9c6c-96538a74824c", "referenceParent": { "type": "Process Definition", "name": "Multi-Period-Market", "code": { "codeName": "Multi-Period-Market", "description": "Produces for each market two files with bollinger channels respectively.", "startMode": { "allMonths": { "run": "false", "minYear": "", "maxYear": "" }, "oneMonth": { "run": "false", "year": "", "month": "" }, "noTime": { "run": "true" }, "fixedInterval": { "run": "false", "interval": 0 } }, "deadWaitTime": 0, "normalWaitTime": 0, "retryWaitTime": 10000, "sleepWaitTime": 3600000, "comaWaitTime": 86400000, "framework": { "name": "Multi-Period-Market", "startDate": {}, "endDate": {} } }, "id": "28be432d-80ca-46b3-859a-55541e24b2b4", "processOutput": { "type": "Process Output", "name": "New Process Output", "outputDatasets": [{ "type": "Output Dataset", "name": "Bollinger Channels", "id": "d804e799-7c12-42f5-8de2-52a3a7d5daa4", "referenceParent": { "type": "Dataset Definition", "name": "Market", "code": { "codeName": "Multi-Period-Market", "type": "Market Files", "validPeriods": ["24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs"], "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Channels/Multi-Period-Market/@Period", "fileName": "@AssetA_@AssetB.json" }, "parentNode": { "type": "Product Definition", "name": "Bollinger Channels", "code": { "codeName": "Bollinger-Channels", "displayName": "Bollinger-Channels", "description": "Two sets of files per period that contains Bollinger-Bands-Channels-Patterns.", "shareWith": "Public" }, "datasets": [], "record": { "type": "Record Definition", "name": "New Record Definition", "properties": [{ "type": "Record Property", "name": "Begin", "code": { "codeName": "begin", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "caf8122c-3a07-4263-a56f-ffb05df281d6" }, "id": "06edb099-ff64-4528-b8c6-599154bc2ddf" }, { "type": "Record Property", "name": "End", "code": { "codeName": "end", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "c8ec0868-8413-468c-88d5-3e43169395e0" }, "id": "94656d1f-508a-4e94-a8d2-013690aac596" }, { "type": "Record Property", "name": "Direction", "code": { "codeName": "direction", "isNumeric": false }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "e913afe9-b610-4777-bc9e-6349d436a90a" }, "id": "edc0f697-f5e2-446f-bae8-8db7adf91d23" }, { "type": "Record Property", "name": "Period", "code": { "codeName": "period", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "83fce657-a0bb-41ee-80d1-9e2ab980c472" }, "id": "eb733f85-6cf5-485e-9bd3-2bf78733c492" }, { "type": "Record Property", "name": "First Moving Average", "code": { "codeName": "firstMovingAverage", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "52490460-35e3-469a-824f-5b139571d4a0" }, "id": "a67a15ee-6f7f-48bd-9d55-82c57efc993b" }, { "type": "Record Property", "name": "Last Moving Average", "code": { "codeName": "lastMovingAverage", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "41edc1ef-293a-4ceb-bf67-8042e8fdc4eb" }, "id": "0f05bffe-d668-4d25-ab67-d55a4a7c8f5d" }, { "type": "Record Property", "name": "First Deviation", "code": { "codeName": "firstDeviation", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "5af02103-9bc9-4e6c-9684-5a612adfa495" }, "id": "eae84509-b689-4a76-9277-eed72af491dd" }, { "type": "Record Property", "name": "Last Deviation", "code": { "codeName": "lastDeviation", "isNumeric": true }, "formula": { "type": "Formula", "code": "// Write your formula here", "id": "bc82d292-e71a-4367-9b07-a0e3982ad60d" }, "id": "d5c32d1f-9e3c-48e8-8025-a17d57c0812e" }], "id": "6c3e68b0-b781-4c53-9ff7-67c3f747ac8a" }, "parentNode": { "type": "Indicator Bot", "name": "Paula", "code": { "codeName": "AAPaula" }, "processes": [], "products": [], "parentNode": { "type": "Team", "name": "Masters", "code": { "codeName": "AAMasters" }, "sensorBots": [], "indicatorBots": [], "tradingBots": [], "plotters": [], "id": "35be7b1c-a0f7-4b5f-9ee1-8fb51595e959" }, "id": "bd0f325d-6f98-468b-8b7b-99a42a175d80" }, "id": "1f111f72-624f-4166-9f99-ab8d785d5267" }, "id": "610cd062-ab88-4892-b711-0fb430305c61" } }, { "type": "Output Dataset", "name": "Bollinger Standard Channels", "id": "e524685d-8da0-41f6-839d-9a4100e6e3fe", "referenceParent": { "type": "Dataset Definition", "name": "Market", "code": { "codeName": "Multi-Period-Market", "type": "Market Files", "validPeriods": ["24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs"], "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Standard-Channels/Multi-Period-Market/@Period", "fileName": "@AssetA_@AssetB.json" }, "parentNode": { "type": "Product Definition", "name": "Bollinger Standard Channels", "code": { "codeName": "Bollinger-Standard-Channels", "displayName": "Bollinger-Standard-Channels", "description": "", "shareWith": "Public" }, "datasets": [], "record": { "type": "Record Definition", "name": "New Record Definition", "properties": [], "id": "9106250d-b042-4e96-9121-c760b4c1eab2" }, "parentNode": { "type": "Indicator Bot", "name": "Paula", "code": { "codeName": "AAPaula" }, "processes": [], "products": [], "parentNode": { "type": "Team", "name": "Masters", "code": { "codeName": "AAMasters" }, "sensorBots": [], "indicatorBots": [], "tradingBots": [], "plotters": [], "id": "35be7b1c-a0f7-4b5f-9ee1-8fb51595e959" }, "id": "bd0f325d-6f98-468b-8b7b-99a42a175d80" }, "id": "94bc3958-cc85-43a1-a178-103e84f42910" }, "id": "22c1f2c6-3838-4657-add8-2e01d7056917" } }, { "type": "Output Dataset", "name": "Bollinger Sub-Channels", "id": "eb0e7947-95e4-4f4a-87ea-1fb430b8b503", "referenceParent": { "type": "Dataset Definition", "name": "Market", "code": { "codeName": "Multi-Period-Market", "type": "Market Files", "validPeriods": ["24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs"], "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Sub-Channels/Multi-Period-Market/@Period", "fileName": "@AssetA_@AssetB.json" }, "parentNode": { "type": "Product Definition", "name": "Bollinger Sub-Channels", "code": { "codeName": "Bollinger-Sub-Channels", "displayName": "Bollinger-Sub-Channels", "description": "Bollinger Sub Channels with slope.", "shareWith": "Public" }, "datasets": [], "record": { "type": "Record Definition", "name": "New Record Definition", "properties": [], "id": "5a780d7f-70df-4e86-8192-eacccafb5ca8" }, "parentNode": { "type": "Indicator Bot", "name": "Paula", "code": { "codeName": "AAPaula" }, "processes": [], "products": [], "parentNode": { "type": "Team", "name": "Masters", "code": { "codeName": "AAMasters" }, "sensorBots": [], "indicatorBots": [], "tradingBots": [], "plotters": [], "id": "35be7b1c-a0f7-4b5f-9ee1-8fb51595e959" }, "id": "bd0f325d-6f98-468b-8b7b-99a42a175d80" }, "id": "080c87fc-4546-4482-ab11-180a33f6d9ab" }, "id": "869f615e-0cc0-44fd-8648-4a951c23a410" } }, { "type": "Output Dataset", "name": "Bollinger Standard Sub-Channels", "id": "dc96b9ac-f8d5-4bf8-a135-45cd5d6369f1", "referenceParent": { "type": "Dataset Definition", "name": "Market", "code": { "codeName": "Multi-Period-Market", "type": "Market Files", "validPeriods": ["24-hs", "12-hs", "08-hs", "06-hs", "04-hs", "03-hs", "02-hs", "01-hs"], "filePath": "AAMasters/AAPaula.1.0/AACloud.1.1/@Exchange/dataSet.V1/Output/Bollinger-Standard-Sub-Channels/Multi-Period-Market/@Period", "fileName": "@AssetA_@AssetB.json" }, "parentNode": { "type": "Product Definition", "name": "Bollinger Standard Sub-Channels", "code": { "codeName": "Bollinger-Standard-Sub-Channels", "displayName": "Bollinger-Standard-Sub-Channels", "description": "Bollinger Standard Sub Channels with slope.", "shareWith": "Public" }, "datasets": [], "record": { "type": "Record Definition", "name": "New Record Definition", "properties": [], "id": "cdbe5e0f-9292-4d3d-b98a-d441e6565b76" }, "parentNode": { "type": "Indicator Bot", "name": "Paula", "code": { "codeName": "AAPaula" }, "processes": [], "products": [], "parentNode": { "type": "Team", "name": "Masters", "code": { "codeName": "AAMasters" }, "sensorBots": [], "indicatorBots": [], "tradingBots": [], "plotters": [], "id": "35be7b1c-a0f7-4b5f-9ee1-8fb51595e959" }, "id": "bd0f325d-6f98-468b-8b7b-99a42a175d80" }, "id": "79ce9c05-8a4c-4b58-850f-288037acc702" }, "id": "f8d44a4d-3771-4a71-97ca-dc604ff565d3" } }], "id": "dd39a54a-3714-446a-9a41-dfd83557664c" }, "processDependencies": { "type": "Process Dependencies", "name": "New Process Dependencies", "statusDependencies": [{ "type": "Status Dependency", "name": "Self Reference", "code": { "mainUtility": "Self Reference" }, "id": "ae627a69-4089-432d-b379-1b12ce4bd75e", "referenceParent": { "type": "Status Report", "name": "New Status Report", "parentNode": { "type": "Process Definition", "name": "Multi-Period-Market", "code": { "codeName": "Multi-Period-Market", "description": "Produces for each market two files with bollinger channels respectively.", "startMode": { "allMonths": { "run": "false", "minYear": "", "maxYear": "" }, "oneMonth": { "run": "false", "year": "", "month": "" }, "noTime": { "run": "true" }, "fixedInterval": { "run": "false", "interval": 0 } }, "deadWaitTime": 0, "normalWaitTime": 0, "retryWaitTime": 10000, "sleepWaitTime": 3600000, "comaWaitTime": 86400000, "framework": { "name": "Multi-Period-Market", "startDate": {}, "endDate": {} } }, "id": "28be432d-80ca-46b3-859a-55541e24b2b4", "parentNode": { "type": "Indicator Bot", "name": "Paula", "code": { "codeName": "AAPaula" }, "processes": [], "products": [], "parentNode": { "type": "Team", "name": "Masters", "code": { "codeName": "AAMasters" }, "sensorBots": [], "indicatorBots": [], "tradingBots": [], "plotters": [], "id": "35be7b1c-a0f7-4b5f-9ee1-8fb51595e959" }, "id": "bd0f325d-6f98-468b-8b7b-99a42a175d80" } }, "id": "af8aded9-002a-475a-88f5-d29573740969" } }, { "type": "Status Dependency", "name": "Market Ending Point", "code": { "mainUtility": "Market Ending Point" }, "id": "4a603114-d464-46db-90a1-62304274117a", "referenceParent": { "type": "Status Report", "name": "New Status Report", "parentNode": { "type": "Process Definition", "name": "Multi-Period-Market", "code": { "codeName": "Multi-Period-Market", "description": "Produces a single file for each time period covering all the market.", "startMode": { "allMonths": { "run": "false", "minYear": "", "maxYear": "" }, "oneMonth": { "run": "false", "year": "", "month": "" }, "noTime": { "run": "true" }, "fixedInterval": { "run": "false", "interval": 0 } }, "deadWaitTime": 0, "normalWaitTime": 0, "retryWaitTime": 10000, "sleepWaitTime": 3600000, "comaWaitTime": 86400000 }, "id": "941a0543-0cc0-4a5d-a782-728d2835c100", "parentNode": { "type": "Indicator Bot", "name": "Chris", "code": { "codeName": "AAChris" }, "processes": [], "products": [], "parentNode": { "type": "Team", "name": "Masters", "code": { "codeName": "AAMasters" }, "sensorBots": [], "indicatorBots": [], "tradingBots": [], "plotters": [], "id": "35be7b1c-a0f7-4b5f-9ee1-8fb51595e959" }, "id": "1b7ecdbd-82e9-4a27-8fdd-467c0ca6bf23" } }, "id": "4f8197fa-2627-46df-bd36-7d30fdb12d8c" } }], "dataDependencies": [{ "type": "Data Dependency", "name": "Chris Bollinger Bands", "id": "ea27be54-93a3-48e3-8c52-72bc397b6c66", "referenceParent": { "type": "Dataset Definition", "name": "Multi-Period-Market", "code": { "codeName": "Multi-Period-Market" }, "parentNode": { "type": "Product Definition", "name": "Bollinger Bands", "code": { "codeName": "Bollinger-Bands", "variableName": "bollingerBand" }, "datasets": [], "record": { "type": "Record Definition", "name": "New Record Definition", "properties": [{ "type": "Record Property", "name": "Begin", "code": { "codeName": "begin", "isNumeric": true }, "id": "1e7186ee-c481-401d-827f-a30ee7434d92" }, { "type": "Record Property", "name": "End", "code": { "codeName": "end", "isNumeric": true }, "id": "15f90f2e-80f0-4575-94d8-6d8957eceee1" }, { "type": "Record Property", "name": "Moving Average", "code": { "codeName": "movingAverage", "isNumeric": true }, "id": "9786a9cd-1eff-4b5c-ae7c-1dde51659f82" }, { "type": "Record Property", "name": "Standard Deviation", "code": { "codeName": "standardDeviation", "isNumeric": true }, "id": "e92d7855-bb18-494e-ab37-a895bbcb8287" }, { "type": "Record Property", "name": "Deviation", "code": { "codeName": "deviation", "isNumeric": true }, "id": "03043530-caa1-416e-8303-840b732e516e" }, { "type": "Record Property", "name": "Direction", "code": { "codeName": "direction", "isNumeric": false, "isCalculated": true }, "formula": { "type": "Formula", "code": "variable.direction", "id": "f72926d9-c869-4b7c-ba1e-b36d134e2bc6" }, "id": "856f24c9-f5f1-491b-98e7-6e1d3c5c5874" }, { "type": "Record Property", "name": "Slope", "code": { "codeName": "slope", "isNumeric": false, "isCalculated": true }, "formula": { "type": "Formula", "code": "variable.slope", "id": "fac935fe-b448-4b34-aed7-b35f70808911" }, "id": "4c027b0c-da8a-4146-a51a-d0a7a126150b" }], "id": "b5a5ec97-7246-42bd-97e4-28fb4a148b2c" }, "calculations": { "type": "Calculations Procedure", "name": "New Calculations Procedure", "initialization": { "type": "Procedure Initialization", "name": "New Procedure Initialization", "code": { "type": "Code", "code": "variable.lastMovingAverage = 0\nvariable.SIDE_TOLERANCE = 0.5 * system.timePeriod / system.ONE_DAY_IN_MILISECONDS\nvariable.SMALL_SLOPE = 1.0 * system.timePeriod / system.ONE_DAY_IN_MILISECONDS\nvariable.MEDIUM_SLOPE = 2.0 * system.timePeriod / system.ONE_DAY_IN_MILISECONDS\nvariable.HIGH_SLOPE = 4.0 * system.timePeriod / system.ONE_DAY_IN_MILISECONDS\n", "id": "f00ac417-cd99-493c-b959-35eddd6fe4f3" }, "id": "d144ab2f-5b4e-4153-806a-d471e9f281dd" }, "loop": { "type": "Procedure Loop", "name": "New Procedure Loop", "code": { "type": "Code", "code": "\nif (variable.lastMovingAverage > indicator.bollingerBand.movingAverage) { variable.direction = \"Down\" }\nif (variable.lastMovingAverage < indicator.bollingerBand.movingAverage) { variable.direction = \"Up\" }\nif (variable.lastMovingAverage === indicator.bollingerBand.movingAverage) { variable.direction = \"Side\" }\n\nvariable.delta = Math.abs(indicator.bollingerBand.movingAverage - variable.lastMovingAverage)\n\nvariable.slope = \"Extreme\"\nif (variable.delta < indicator.bollingerBand.movingAverage * variable.HIGH_SLOPE / 100) { variable.slope = \"Steep\" }\nif (variable.delta < indicator.bollingerBand.movingAverage * variable.MEDIUM_SLOPE / 100) { variable.slope = \"Medium\" }\nif (variable.delta < indicator.bollingerBand.movingAverage * variable.SMALL_SLOPE / 100) { variable.slope = \"Gentle\" }\nif (variable.delta < indicator.bollingerBand.movingAverage * variable.SIDE_TOLERANCE / 100) { variable.slope = \"Side\" }\n\nvariable.lastMovingAverage = indicator.bollingerBand.movingAverage", "id": "14fc0c9c-cd10-4931-95b5-4bc7d549942a" }, "id": "8a669548-845b-4d80-ae96-29f68e9c9ac7" }, "id": "d72c7cb2-8886-4101-a83a-f9788b8400a0" }, "dataBuilding": { "type": "Data Building Procedure", "name": "New Data Building Procedure", "id": "139484b3-3a3f-4268-801e-a8c441746c7a" }, "parentNode": { "type": "Indicator Bot", "name": "Chris", "code": { "codeName": "AAChris" }, "processes": [], "products": [], "parentNode": { "type": "Team", "name": "Masters", "code": { "codeName": "AAMasters" }, "sensorBots": [], "indicatorBots": [], "tradingBots": [], "plotters": [], "id": "35be7b1c-a0f7-4b5f-9ee1-8fb51595e959" }, "id": "1b7ecdbd-82e9-4a27-8fdd-467c0ca6bf23" }, "id": "29088877-8d63-4217-8d34-8742afc262f4" }, "id": "f5b2a7d8-fc32-44a3-a002-9b0fc30a9719" } }], "id": "8b509294-6028-40e2-88a8-655a34245ed8" }, "statusReport": { "type": "Status Report", "name": "New Status Report", "parentNode": { "type": "Process Definition", "name": "Multi-Period-Market", "code": { "codeName": "Multi-Period-Market", "description": "Produces for each market two files with bollinger channels respectively.", "startMode": { "allMonths": { "run": "false", "minYear": "", "maxYear": "" }, "oneMonth": { "run": "false", "year": "", "month": "" }, "noTime": { "run": "true" }, "fixedInterval": { "run": "false", "interval": 0 } }, "deadWaitTime": 0, "normalWaitTime": 0, "retryWaitTime": 10000, "sleepWaitTime": 3600000, "comaWaitTime": 86400000, "framework": { "name": "Multi-Period-Market", "startDate": {}, "endDate": {} } }, "id": "28be432d-80ca-46b3-859a-55541e24b2b4", "parentNode": { "type": "Indicator Bot", "name": "Paula", "code": { "codeName": "AAPaula" }, "processes": [], "products": [], "parentNode": { "type": "Team", "name": "Masters", "code": { "codeName": "AAMasters" }, "sensorBots": [], "indicatorBots": [], "tradingBots": [], "plotters": [], "id": "35be7b1c-a0f7-4b5f-9ee1-8fb51595e959" }, "id": "bd0f325d-6f98-468b-8b7b-99a42a175d80" } }, "id": "af8aded9-002a-475a-88f5-d29573740969" }, "executionStartedEvent": { "type": "Execution Started Event", "name": "New Execution Started Event", "id": "f4720e04-5def-4c0b-be42-33e50ac6a6b7", "referenceParent": { "type": "Execution Finished Event", "name": "New Execution Finished Event", "id": "4a9c8cc7-0ebf-43eb-b7f9-0b280630ff67", "parentNode": { "type": "Process Definition", "name": "Multi-Period-Market", "id": "941a0543-0cc0-4a5d-a782-728d2835c100", "code": { "codeName": "Multi-Period-Market", "description": "Produces a single file for each time period covering all the market.", "startMode": { "allMonths": { "run": "false", "minYear": "", "maxYear": "" }, "oneMonth": { "run": "false", "year": "", "month": "" }, "noTime": { "run": "true" }, "fixedInterval": { "run": "false", "interval": 0 } }, "deadWaitTime": 0, "normalWaitTime": 0, "retryWaitTime": 10000, "sleepWaitTime": 3600000, "comaWaitTime": 86400000 } } } }, "executionFinishedEvent": { "type": "Execution Finished Event", "name": "New Execution Finished Event", "id": "671530dc-5ba5-4c8d-bc23-f228e22c56b3", "parentNode": { "type": "Process Definition", "name": "Multi-Period-Market", "id": "28be432d-80ca-46b3-859a-55541e24b2b4", "code": { "codeName": "Multi-Period-Market", "description": "Produces for each market two files with bollinger channels respectively.", "startMode": { "allMonths": { "run": "false", "minYear": "", "maxYear": "" }, "oneMonth": { "run": "false", "year": "", "month": "" }, "noTime": { "run": "true" }, "fixedInterval": { "run": "false", "interval": 0 } }, "deadWaitTime": 0, "normalWaitTime": 0, "retryWaitTime": 10000, "sleepWaitTime": 3600000, "comaWaitTime": 86400000, "framework": { "name": "Multi-Period-Market", "startDate": {}, "endDate": {} } } } } } }], "id": "27564838-24b1-4814-af8c-ec65accb05d1" }, "id": "aa0f2533-460c-464f-ad77-6ae4cadd1178" } -} - -require('dotenv').config(); - -global.WRITE_LOGS_TO_FILES = process.env.WRITE_LOGS_TO_FILES - -/* Default parameters can be changed by the execution configuration */ -global.EXCHANGE_NAME = 'Poloniex' -global.MARKET = { assetA: 'USDT', assetB: 'BTC' } -global.CLONE_EXECUTOR = { codeName: 'AACloud', version: '1.1' } // NOTE: To refactor the name of this variable you would need to go through the bots code that are using it. - -/* -We need to count how many process instances we deployd and how many of them have already finished their job, either -because they just finished or because there was a request to stop the proceses. In this way, once we reach the -amount of instances started, we can safelly destroy the rest of the objects running and let this nodejs process die. -*/ - -global.ENDED_PROCESSES_COUNTER = 0 -global.TOTAL_PROCESS_INSTANCES_CREATED = 0 - /* Here we listen for the message to stop this Task / Process comming from the Task Manager, which is the paret of this node js process. */ process.on('message', message => { if (message === 'Stop this Task') { @@ -133,14 +93,61 @@ global.EXIT_NODE_PROCESS = function exitProcess() { setTimeout(process.exit, 10000) // We will give 10 seconds to logs be written on file } +require('dotenv').config(); + +global.WRITE_LOGS_TO_FILES = process.env.WRITE_LOGS_TO_FILES + +/* Default parameters can be changed by the execution configuration */ +global.EXCHANGE_NAME = 'Poloniex' +global.MARKET = { assetA: 'USDT', assetB: 'BTC' } +global.CLONE_EXECUTOR = { codeName: 'AACloud', version: '1.1' } // NOTE: To refactor the name of this variable you would need to go through the bots code that are using it. + +/* +We need to count how many process instances we deployd and how many of them have already finished their job, either +because they just finished or because there was a request to stop the proceses. In this way, once we reach the +amount of instances started, we can safelly destroy the rest of the objects running and let this nodejs process die. +*/ + +global.ENDED_PROCESSES_COUNTER = 0 +global.TOTAL_PROCESS_INSTANCES_CREATED = 0 + +/* + +We read the first string sent as an argument when the process was created by the Task Manager. There we will find the information of the identity +of this Task and know exactly what to run within this server instance. + +*/ +global.TASK_NODE = process.argv[2] + /* Setting up the global Event Handler */ const EVENT_HANDLER_MODULE = require('./SystemEventHandler.js'); const IPC = require('node-ipc'); global.SYSTEM_EVENT_HANDLER = EVENT_HANDLER_MODULE.newSystemEventHandler(IPC) -global.SYSTEM_EVENT_HANDLER.initialize('Task Server', bootLoader) +global.SYSTEM_EVENT_HANDLER.initialize('Task Server', preLoader) global.STOP_TASK_GRACEFULLY = false; +function preLoader() { + if (global.TASK_NODE !== undefined) { + /* The Task Manager sent the info via a process argument. */ + try { + global.TASK_NODE = JSON.parse(global.TASK_NODE) + console.log('[INFO] Task Server -> server -> preLoader -> global.TASK_NODE = ' + JSON.stringify(global.TASK_NODE)) + } catch (err) { + console.log('[ERROR] Task Server -> server -> preLoader -> vglobal.TASK_NODE -> ' + err.stack) + } + bootLoader() + } + else { /* This process was started not by the Task Manager, but independently (most likely for debugging purposes). In this case we listen to an event with the Task Info */ + console.log('[INFO] Task Server -> server -> preLoader -> Waiting for event to start debugging...') + global.SYSTEM_EVENT_HANDLER.listenToEvent('Task Server', 'Debug Task Started', undefined, undefined, undefined, startDebugging) + function startDebugging(message) { + global.TASK_NODE = JSON.parse(message.event.definition) + bootLoader() + } + } +} + function bootLoader() { /* Heartbeat sent to the UI */