exports.newFoundationsProcessModulesDataset = function (processIndex) { /* This module represents a Dataset at a certain localtion on the network, and it is able to load a file from that dataset or write one into it. */ const MODULE_NAME = "Dataset"; let thisObject = { node: undefined, networkNode: undefined, exchange: undefined, market: undefined, product: undefined, initialize: initialize, finalize: finalize, getTextFile: getTextFile, createTextFile: createTextFile }; /* Storage account to be used here. */ let fileStorage return thisObject; function initialize(exchange, market, dataDependency, callBackFunction) { try { thisObject.node = dataDependency.referenceParent; thisObject.exchange = exchange thisObject.market = market /* Some very basic validations that we have all the information needed. */ if (thisObject.node === undefined) { TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] initialize -> Data Dependency without Reference Parent -> dataDependency = " + JSON.stringify(dataDependency)); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); return } if (thisObject.node.config.codeName === undefined) { TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] initialize -> Dataset witn no codeName defined -> Product Dataset = " + JSON.stringify(thisObject.node)); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); return } if (thisObject.node.parentNode === undefined) { TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] initialize -> Dataset not attached to a Product Definition -> Dataset = " + JSON.stringify(thisObject.node)); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); return } if (thisObject.node.parentNode.config.codeName === undefined) { TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] initialize -> Product Definition witn no codeName defined -> Product Definition = " + JSON.stringify(thisObject.node.parentNode)); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); return } if (thisObject.node.parentNode.parentNode === undefined) { TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] initialize -> Product Definition not attached to a Bot -> Product Definition = " + JSON.stringify(thisObject.node.parentNode)); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); return } if (thisObject.node.parentNode.parentNode.config.codeName === undefined) { TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] initialize -> Bot witn no codeName defined. Bot = " + JSON.stringify(thisObject.node.parentNode.parentNode)); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); return } if (thisObject.node.parentNode.parentNode.parentNode === undefined) { TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] initialize -> Bot not attached to a Data Mine or Trading Mine. Bot = " + JSON.stringify(thisObject.node.parentNode.parentNode)); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); return } if (thisObject.node.parentNode.parentNode.parentNode.config.codeName === undefined) { TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] initialize -> Data Mine witn no codeName defined. Data Mine = " + JSON.stringify(thisObject.node.parentNode.parentNode.parentNode)); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); return } /* Now we will see where do we need to fetch this data from. */ let network = TS.projects.foundations.globals.taskConstants.NETWORK_NODE let productDefinition = thisObject.node.parentNode thisObject.product = productDefinition.config.singularVariableName /* We will find the networkNode that leads to this Product Definition and is related to this exchange and market. */ let networkNode = fincNetworkNode(network, productDefinition, thisObject.exchange, thisObject.market) if (networkNode === undefined) { TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[WARN] initialize -> Network Node not found.") TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[WARN] initialize -> Initialization Failed because we could not find where the data of this dataset is located within the network. Check the logs for more info."); TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[WARN] initialize -> Could not find where " + productDefinition.name + " for " + thisObject.exchange + " " + thisObject.market + " is stored within the network."); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_OK_RESPONSE, false); return } /* We found where the data is located on the network. */ TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[INFO] initialize -> Retrieving data from " + networkNode.name + " -> host = " + networkNode.config.host + ' -> port = ' + networkNode.config.webPort + '.') fileStorage = TS.projects.foundations.taskModules.fileStorage.newFileStorage(processIndex, networkNode.config.host, networkNode.config.webPort); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_OK_RESPONSE, true); } catch (err) { TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); } } function finalize() { fileStorage = undefined thisObject.networkNode = undefined thisObject.exchange = undefined thisObject.market = undefined bot = undefined thisObject = undefined } function getTextFile(pFolderPath, pFileName, callBackFunction) { try { let mine = thisObject.node.parentNode.parentNode.parentNode.config.codeName let mineType = thisObject.node.parentNode.parentNode.parentNode.type.replace(' ', '-') let project = thisObject.node.parentNode.parentNode.parentNode.project let botCodeName = thisObject.node.parentNode.parentNode.config.codeName let filePathRoot = 'Project/' + project + "/" + mineType + "/" + mine + "/" + botCodeName + '/' + thisObject.exchange + "/" + thisObject.market let filePath = filePathRoot + "/Output/" + pFolderPath; filePath += '/' + pFileName fileStorage.getTextFile(filePath, onFileReceived); function onFileReceived(err, text) { callBackFunction(err, text); } } catch (err) { TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] 'getTextFile' -> err = " + err.stack); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); } } function createTextFile(pFolderPath, pFileName, pFileContent, callBackFunction) { try { TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[INFO] createTextFile -> pFolderPath = " + pFolderPath) TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[INFO] createTextFile -> pFileName = " + pFileName) let ownerId = thisObject.node.dataMine + "-" + thisObject.node.bot let botId = TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.parentNode.config.codeName + "-" + TS.projects.foundations.globals.taskConstants.TASK_NODE.bot.processes[processIndex].referenceParent.parentNode.config.codeName if (ownerId !== botId) { let customErr = { result: TS.projects.foundations.globals.standardResponses.CUSTOM_FAIL_RESPONSE.result, message: "Only bots owners of a Data Set can create text files on them." }; TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] save -> customErr = " + customErr.message); callBackFunction(customErr); return; } let filePathRoot = 'Project/' + thisObject.node.project + "/" + thisObject.node.mineType + "/" + thisObject.node.dataMine + "/" + thisObject.node.bot + '/' + thisObject.exchange + "/" + thisObject.market let filePath = filePathRoot + "/Output/" + pFolderPath + '/' + pFileName; fileStorage.createTextFile(filePath, pFileContent, onFileCreated); function onFileCreated(err) { callBackFunction(err); } } catch (err) { TS.projects.foundations.globals.processVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).UNEXPECTED_ERROR = err TS.projects.foundations.globals.loggerVariables.VARIABLES_BY_PROCESS_INDEX_MAP.get(processIndex).BOT_MAIN_LOOP_LOGGER_MODULE_OBJECT.write(MODULE_NAME, "[ERROR] 'createTextFile' -> err = " + err.stack); callBackFunction(TS.projects.foundations.globals.standardResponses.DEFAULT_FAIL_RESPONSE); } } function fincNetworkNode(network, productDefinition, exchange, market) { /* The problem that we need to solve here is the following: A. We are interested in a particular Exchange and Market. B. We have the Network we received from the UI whe the user ran the Task. C. We have the Product Definition that is the parent node of the Data Set represented by this object. D. This Product Definition is referenced by one or more Data Products nodes at some branch of the Network Hierarchy. E. We need to find the right Data Product node, the one who is itself a descendent of the Market Data Products node that is referencing the market and exchange that we have as a parameter of this function. So, the strategy we will implement is the following: 1. We will scan all the branches of the Network received from the UI. 2. Once we find a Market Data Products, Market Trading Products o Market Learning Products we will check that they are referencing the market and exchange we need, other wise we ignore them and continue with the scanning. 3. Once found, we will go into their own branches and find a path until the Product Definition we need to reach. 4. Once reached, we will know which Network Node is on the full path from the Network to the Product Definition and we solved the problem. */ let found = false let networkNode let splittedMarket = market.split('-') let baseAsset = splittedMarket[0] let quotedAsset = splittedMarket[1] scanNodeMesh(network) if (found === true) { return networkNode } else { return } function scanNodeMesh(startingNode) { if (startingNode === undefined) { return } let schemaDocument = TS.projects.foundations.globals.taskConstants.APP_SCHEMA_MAP.get(startingNode.project + '-' + startingNode.type) if (schemaDocument === undefined) { return } if (startingNode.id === productDefinition.id) { /* We reached the point that we found a path to the Product Definition. Now we know that the last netwrokNode is the node that has the correct path. */ found = true return } if (startingNode.type === 'Network Node') { /* We will store the Network Node here so that if we find the rignt path we can know from which Netwrok Node it going through. */ networkNode = startingNode } if ( startingNode.type === 'Market Data Products' || startingNode.type === 'Market Trading Products' || startingNode.type === 'Market Learning Products' ) { /* We will check that this guy is referencing the right market and the market is a descendant of the right exchange. Otherwise we wont process their children. */ if (startingNode.referenceParent === undefined) { return } if (startingNode.referenceParent.baseAsset === undefined) { return } if (startingNode.referenceParent.quotedAsset === undefined) { return } if (startingNode.referenceParent.baseAsset.referenceParent === undefined) { return } if (startingNode.referenceParent.quotedAsset.referenceParent === undefined) { return } if (startingNode.referenceParent.baseAsset.referenceParent.config.codeName !== baseAsset) { return } if (startingNode.referenceParent.quotedAsset.referenceParent.config.codeName !== quotedAsset) { return } if (startingNode.referenceParent.parentNode === undefined) { return } if (startingNode.referenceParent.parentNode.parentNode === undefined) { return } if (startingNode.referenceParent.parentNode.parentNode.config.codeName !== exchange) { return } } /* We scan through this node children */ if (schemaDocument.childrenNodesProperties !== undefined) { for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) { let property = schemaDocument.childrenNodesProperties[i] switch (property.type) { case 'node': { if (found !== true) { scanNodeMesh(startingNode[property.name]) } } break case 'array': { let startingNodePropertyArray = startingNode[property.name] if (startingNodePropertyArray !== undefined) { for (let m = 0; m < startingNodePropertyArray.length; m++) { if (found !== true) { scanNodeMesh(startingNodePropertyArray[m]) } } } break } } } } /* We scan parents nodes. */ if (startingNode.parentNode !== undefined) { if (found !== true) { scanNodeMesh(startingNode.parentNode) } } /* We scan reference parents too. */ if (startingNode.referenceParent !== undefined) { if (found !== true) { scanNodeMesh(startingNode.referenceParent) } } } } };