diff --git a/AppSchema.json b/AppSchema.json index e177d39e4..cf4124a40 100644 --- a/AppSchema.json +++ b/AppSchema.json @@ -1245,7 +1245,7 @@ "config": true }, "initialValues": { - "code": "{ \n\"ipAddress\": \"\", \n\"webPort\": \"\", \n\"webSocketsPort\": \"\"\n}" + "code": "{ \n\"host\": \"\", \n\"webPort\": \"\", \n\"webSocketsPort\": \"\"\n}" }, "isTitleAllwaysVisible": true, "addLeftIcons": true, @@ -1322,7 +1322,6 @@ "actionFunction": "payload.onMenuItemClick" } ], - "isTitleAllwaysVisible": true, "addLeftIcons": true, "level": 1, "chainAttachesTo": { @@ -1360,6 +1359,16 @@ "iconPathOff": "paper-plane", "actionFunction": "payload.onMenuItemClick" }, + { + "action": "Debug Task", + "label": "Debug", + "workingLabel": "Debugging", + "workDoneLabel": "Debug Request Sent", + "workFailedLabel": "Task Cannot be Debugged", + "iconPathOn": "status-dependency", + "iconPathOff": "status-dependency", + "actionFunction": "payload.onMenuItemClick" + }, { "action": "Add UI Object", "disableIfPropertyIsDefined": true, @@ -6217,12 +6226,6 @@ }, "propertyNameAtParent": "testingEnvironment", "properties": [ - { - "name": "taskManagers", - "type": "array", - "childType": "Task Manager", - "autoAdd": true - }, { "name": "exchangeTasks", "type": "array", @@ -6280,12 +6283,6 @@ }, "propertyNameAtParent": "productionEnvironment", "properties": [ - { - "name": "taskManagers", - "type": "array", - "childType": "Task Manager", - "autoAdd": true - }, { "name": "exchangeTasks", "type": "array", @@ -6442,12 +6439,6 @@ }, "propertyNameAtParent": "sessionBasedData", "properties": [ - { - "name": "sessionReferences", - "type": "array", - "childType": "Session Reference", - "autoAdd": true - }, { "name": "exchangeSessions", "type": "array", diff --git a/CanvasApp/Canvas.js b/CanvasApp/Canvas.js index 1d0e440d0..b13ac359c 100644 --- a/CanvasApp/Canvas.js +++ b/CanvasApp/Canvas.js @@ -130,8 +130,6 @@ function newCanvas () { animation.initialize() thisObject.animation = animation - /* Low Level Infraestructure First */ - animation.addCallBackFunction('System Event Handler Physics', eventsServerClient.physics) /* Spcaces Physics */ animation.addCallBackFunction('CockpitSpace Physics', thisObject.cockpitSpace.physics) diff --git a/CanvasApp/ChartingSpace/PlottersManager.js b/CanvasApp/ChartingSpace/PlottersManager.js index 2b36cf693..a0002b6fa 100644 --- a/CanvasApp/ChartingSpace/PlottersManager.js +++ b/CanvasApp/ChartingSpace/PlottersManager.js @@ -146,6 +146,13 @@ function newPlottersManager () { } } + let host = layer.networkNode.code.host + let webPort = layer.networkNode.code.webPort + if (host === undefined) { host = 'localhost' } + if (webPort === undefined) { webPort = window.location.port } + + let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(layer.networkNode.id) + storage.initialize( dataMine, bot, @@ -155,6 +162,9 @@ function newPlottersManager () { market, datetime, timeFrame, + host, + webPort, + eventsServerClient, onProductStorageInitialized ) diff --git a/CanvasApp/DesignSpace/Workspace/FunctionLibraries/SessionFunctions.js b/CanvasApp/DesignSpace/Workspace/FunctionLibraries/SessionFunctions.js index 6d0b3d230..e1f7883e2 100644 --- a/CanvasApp/DesignSpace/Workspace/FunctionLibraries/SessionFunctions.js +++ b/CanvasApp/DesignSpace/Workspace/FunctionLibraries/SessionFunctions.js @@ -7,26 +7,15 @@ function newSessionFunctions () { return thisObject function runSession (node, functionLibraryProtocolNode, functionLibraryDependenciesFilter, callBackFunction) { - /* We can not run a sessionif its parent process is not running. Less if it does not have a parent. */ - if (node.payload.parentNode === undefined) { - node.payload.uiObject.setErrorMessage('Session needs a Process Instance parent to be able to run.') + if (validations(node) !== true) { callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) return } - if (node.payload.parentNode.payload.uiObject.isRunning !== true) { - node.payload.uiObject.setErrorMessage('Session needs a Process Instance parent to be running to be able to run.') - callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) - return - } + let networkNode = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode + let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(networkNode.id) - if (node.payload.referenceParent === undefined) { - node.payload.uiObject.setErrorMessage('Session needs to reference a Trading System.') - callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) - return - } - - node.payload.uiObject.run(callBackFunction) + node.payload.uiObject.run(eventsServerClient, callBackFunction) let key = node.name + '-' + node.type + '-' + node.id @@ -77,9 +66,65 @@ function newSessionFunctions () { } function stopSession (node, functionLibraryProtocolNode, callBackFunction) { + if (validations(node) !== true) { + callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) + return + } + + let networkNode = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode + let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(networkNode.id) + let key = node.name + '-' + node.type + '-' + node.id eventsServerClient.raiseEvent(key, 'Stop Session') node.payload.uiObject.stop(callBackFunction) } + + function validations (node) { + if (node.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Session needs a Process Instance parent to be able to run.') + return + } + + if (node.payload.parentNode.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Session needs to be inside a Trading Process Instance.') + return + } + + if (node.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Session needs to be inside a Task.') + return + } + + if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Session needs to be inside a Task Manager.') + return + } + + if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Session needs to be inside Exchange Tasks.') + return + } + + if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Session needs to be inside a Testing or Production Environment.') + return + } + + if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Session needs to be inside a Network Node.') + return + } + + if (node.payload.parentNode.payload.uiObject.isRunning !== true) { + node.payload.uiObject.setErrorMessage('Session needs a Process Instance parent to be running.') + return + } + + if (node.payload.referenceParent === undefined) { + node.payload.uiObject.setErrorMessage('Session needs to reference a Trading System.') + return + } + return true + } } diff --git a/CanvasApp/DesignSpace/Workspace/FunctionLibraries/TaskFunctions.js b/CanvasApp/DesignSpace/Workspace/FunctionLibraries/TaskFunctions.js index 6c89285ed..4a83f27db 100644 --- a/CanvasApp/DesignSpace/Workspace/FunctionLibraries/TaskFunctions.js +++ b/CanvasApp/DesignSpace/Workspace/FunctionLibraries/TaskFunctions.js @@ -12,20 +12,18 @@ function newTaskFunctions () { return thisObject - function runTask (node, functionLibraryProtocolNode, callBackFunction) { - /* Check if it is possible to Run or not */ - if (node.bot === undefined) { - callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) - return - } - if (node.bot.processes.length === 0) { + function runTask (node, functionLibraryProtocolNode, isDebugging, callBackFunction) { + if (validations(node) !== true) { callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) return } + let networkNode = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode + let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(networkNode.id) + for (let i = 0; i < node.bot.processes.length; i++) { let process = node.bot.processes[i] - process.payload.uiObject.run() + process.payload.uiObject.run(eventsServerClient) } let lightingPath = '->Task->' + @@ -66,17 +64,25 @@ function newTaskFunctions () { definition: JSON.stringify(definition) // <- We need to do this workaround in order no to send unescaped charactars to the taskManager. } - if (node.payload.parentNode === undefined) { - callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) + if (isDebugging === true) { + callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE) eventsServerClient.raiseEvent('Task Server', 'Debug Task Started', event) return } - node.payload.uiObject.run(callBackFunction) + node.payload.uiObject.run(eventsServerClient, callBackFunction) eventsServerClient.raiseEvent('Task Manager', 'Run Task', event) } function stopTask (node, functionLibraryProtocolNode, callBackFunction) { + if (validations(node) !== true) { + callBackFunction(GLOBAL.DEFAULT_FAIL_RESPONSE) + return + } + + let networkNode = node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode + let eventsServerClient = canvas.designSpace.workspace.eventsServerClients.get(networkNode.id) + let event = { taskId: node.id, taskName: node.name @@ -94,6 +100,38 @@ function newTaskFunctions () { } } + function validations (node) { + if (node.bot === undefined) { + node.payload.uiObject.setErrorMessage('Task needs to have a Bot Instance.') + return + } + if (node.bot.processes.length === 0) { + node.payload.uiObject.setErrorMessage('Task Bot Instance needs to have al least once Process Instance.') + return + } + + if (node.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Task needs to be inside a Task Manager.') + return + } + + if (node.payload.parentNode.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Task needs to be inside Exchange Tasks.') + return + } + + if (node.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Task needs to be inside a Testing or Production Environment or a Data Mining node.') + return + } + + if (node.payload.parentNode.payload.parentNode.payload.parentNode.payload.parentNode === undefined) { + node.payload.uiObject.setErrorMessage('Task needs to be inside a Network Node.') + return + } + return true + } + function runAllTasks (taskManager, functionLibraryProtocolNode) { for (let i = 0; i < taskManager.tasks.length; i++) { let node = taskManager.tasks[i] diff --git a/CanvasApp/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js b/CanvasApp/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js index eadf4355e..d6253f558 100644 --- a/CanvasApp/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js +++ b/CanvasApp/DesignSpace/Workspace/FunctionLibraries/UiObjectsFromNodes.js @@ -37,7 +37,7 @@ function newUiObjectsFromNodes () { for (let i = 0; i < includeDataMines.length; i++) { let name = includeDataMines[i] - blobService.getBlobToText('DataMines' + '/' + name, undefined, onFileReceived, true) + blobService.getFileFromHost('DataMines' + '/' + name, onFileReceived, true) function onFileReceived (err, text, response) { if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { console.log('Cannot load included Data Mine ' + name + '. The workspace can not be loaded.') @@ -66,7 +66,7 @@ function newUiObjectsFromNodes () { for (let i = 0; i < includeTradingSystems.length; i++) { let name = includeTradingSystems[i] - blobService.getBlobToText('TradingSystems' + '/' + name, undefined, onFileReceived, true) + blobService.getFileFromHost('TradingSystems' + '/' + name, onFileReceived, true) function onFileReceived (err, text, response) { if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { console.log('Cannot load included Data Mine ' + name + '. The workspace can not be loaded.') @@ -95,7 +95,7 @@ function newUiObjectsFromNodes () { for (let i = 0; i < includeSuperScripts.length; i++) { let name = includeSuperScripts[i] - blobService.getBlobToText('SuperScripts' + '/' + name, undefined, onFileReceived, true) + blobService.getFileFromHost('SuperScripts' + '/' + name, onFileReceived, true) function onFileReceived (err, text, response) { if (err && err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { console.log('Cannot load included Data Mine ' + name + '. The workspace can not be loaded.') diff --git a/CanvasApp/DesignSpace/Workspace/Workspace.js b/CanvasApp/DesignSpace/Workspace/Workspace.js index dedea1c5b..a58fb46a1 100644 --- a/CanvasApp/DesignSpace/Workspace/Workspace.js +++ b/CanvasApp/DesignSpace/Workspace/Workspace.js @@ -10,6 +10,7 @@ function newWorkspace () { container: undefined, enabled: false, nodeChildren: undefined, + eventsServerClients: new Map(), save: saveWorkspace, getHierarchyHeads: getHierarchyHeads, getNodeThatIsOnFocus: getNodeThatIsOnFocus, @@ -93,6 +94,7 @@ function newWorkspace () { thisObject.workspaceNode = JSON.parse(savedWorkspace) } functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode) + setupEventsServerClients() thisObject.enabled = true setInterval(saveWorkspace, 60000) @@ -101,6 +103,38 @@ function newWorkspace () { } } + function setupEventsServerClients () { + for (let i = 0; i < thisObject.workspaceNode.rootNodes.length; i++) { + let rootNode = thisObject.workspaceNode.rootNodes[i] + + if (rootNode.type === 'Network') { + for (let j = 0; j < rootNode.networkNodes.length; j++) { + let networkNode = rootNode.networkNodes[j] + + let host + let webSocketsPort + /* At this point the node does not have the payload property yet, that is why we have to do this manually */ + try { + let code = JSON.parse(networkNode.code) + host = code.host + webSocketsPort = code.webSocketsPort + } catch (err) { + console.log('[ERROR] networkNode ' + networkNode.name + ' has an invalid configuration. Cannot know the host name and webSocketsPort.') + return + } + + if (host === undefined) { host = 'localhost' } + if (webSocketsPort === undefined) { webSocketsPort = '8080' } + + let eventsServerClient = newEventsServerClient(host, webSocketsPort) + eventsServerClient.initialize() + + thisObject.eventsServerClients.set(networkNode.id, eventsServerClient) + } + } + } + } + function chainDetachNode (node) { functionLibraryChainAttachDetach.chainDetachNode(node, thisObject.workspaceNode.rootNodes) } @@ -130,6 +164,19 @@ function newWorkspace () { } function physics () { + eventsServerClientsPhysics() + replacingWorkspacePhysics() + } + + function eventsServerClientsPhysics () { + thisObject.eventsServerClients.forEach(applyPhysics) + + function applyPhysics (eventServerClient) { + eventServerClient.physics() + } + } + + function replacingWorkspacePhysics () { if (thisObject.enabled !== true) { return } if (workingAtTask > 0) { @@ -151,6 +198,7 @@ function newWorkspace () { break case 4: functionLibraryUiObjectsFromNodes.recreateWorkspace(thisObject.workspaceNode, true) + setupEventsServerClients() workingAtTask++ break case 5: @@ -358,10 +406,15 @@ function newWorkspace () { downloadText(fileName, text) } + break + case 'Debug Task': + { + functionLibraryTaskFunctions.runTask(payload.node, functionLibraryProtocolNode, true, callBackFunction) + } break case 'Run Task': { - functionLibraryTaskFunctions.runTask(payload.node, functionLibraryProtocolNode, callBackFunction) + functionLibraryTaskFunctions.runTask(payload.node, functionLibraryProtocolNode, false, callBackFunction) } break case 'Stop Task': diff --git a/CanvasApp/EventsServerClient.js b/CanvasApp/EventsServerClient.js index f5d05ea8f..a94c1495a 100644 --- a/CanvasApp/EventsServerClient.js +++ b/CanvasApp/EventsServerClient.js @@ -1,5 +1,5 @@ -function newEventsServerClient () { +function newEventsServerClient (host, port) { /* Web Sockets Connection */ const MODULE_NAME = 'System Event Handler' @@ -8,7 +8,7 @@ function newEventsServerClient () { const logger = newWebDebugLog() logger.fileName = MODULE_NAME - const WEB_SOCKETS_URL = 'ws://localhost:8080' + const WEB_SOCKETS_URL = 'ws://' + host + ':' + port + '' let WEB_SOCKETS_CONNECTION let thisObject = { @@ -56,12 +56,7 @@ function newEventsServerClient () { responseWaiters.set(command.callerId, responseCallBack) } - if (WEB_SOCKETS_CONNECTION.readyState === 1) { - // 1 means connected and ready. - sendToWebSocketServer(command) - } else { - console.log('WebSocket message could not be sent because the connection was not ready. Message = ' + JSON.stringify(command)) - } + sendToWebSocketServer(command) } function sendToWebSocketServer (command) { @@ -72,7 +67,12 @@ function newEventsServerClient () { commandsSentByTimestamp.set(stringNonce, timestamp) let messageToWebSocketServer = 'Web Browser' + '|*|' + stringNonce + '|*|' + JSON.stringify(command) - WEB_SOCKETS_CONNECTION.send(messageToWebSocketServer) + + if (WEB_SOCKETS_CONNECTION.readyState === 1) { + WEB_SOCKETS_CONNECTION.send(messageToWebSocketServer) + } else { + console.log('WebSocket message could not be sent because the connection was not ready. Will retry soon. Message = ' + JSON.stringify(command)) + } } function createEventHandler (eventHandlerName, callerId, responseCallBack) { @@ -153,7 +153,7 @@ function newEventsServerClient () { } if (thisObject.isConnected() !== true) { - canvas.cockpitSpace.setStatus('Connection with the local backend lost. Please check that all localhost servers are running.', 100, canvas.cockpitSpace.statusTypes.WARNING) + canvas.cockpitSpace.setStatus('Connecting with ' + host + '. Please hold on until the connection can be stablished.', 100, canvas.cockpitSpace.statusTypes.WARNING) } else { retryCommandsPhysics() } diff --git a/CanvasApp/FloatingSpace/CircularProgressBar.js b/CanvasApp/FloatingSpace/CircularProgressBar.js index 8e6a55336..d662589c8 100644 --- a/CanvasApp/FloatingSpace/CircularProgressBar.js +++ b/CanvasApp/FloatingSpace/CircularProgressBar.js @@ -22,27 +22,35 @@ function newCircularProgressBar () { thisObject.container.frame.position.y = 0 let opacityCounters = [] - let eventSubscriptionIdHeartbeat - let needToDrawRing = true + let eventsServerClient return thisObject function finalize () { - let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id - if (eventSubscriptionIdHeartbeat !== undefined) { - eventsServerClient.stopListening(key, eventSubscriptionIdHeartbeat) - } + finalizeEventsServerClient() thisObject.container = undefined thisObject.payload = undefined thisObject.fitFunction = undefined } - function initialize (payload) { + function finalizeEventsServerClient () { + if (eventsServerClient !== undefined) { + let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id + if (eventSubscriptionIdHeartbeat !== undefined) { + eventsServerClient.stopListening(key, eventSubscriptionIdHeartbeat) + } + } + } + + function initialize (payload, pEventsServerClient) { thisObject.payload = payload + finalizeEventsServerClient() + eventsServerClient = pEventsServerClient + for (let i = 0; i < 60; i++) { opacityCounters.push(0) } diff --git a/CanvasApp/FloatingSpace/UiObject.js b/CanvasApp/FloatingSpace/UiObject.js index 43f389648..136c3c9a0 100644 --- a/CanvasApp/FloatingSpace/UiObject.js +++ b/CanvasApp/FloatingSpace/UiObject.js @@ -117,17 +117,12 @@ function newUiObject () { let referenceLineCounter = 0 let chainLineCounter = 0 + let eventsServerClient + return thisObject function finalize () { - let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id - - if (eventSubscriptionIdOnRunning !== undefined) { - eventsServerClient.stopListening(key, eventSubscriptionIdOnRunning, 'UiObject') - } - if (eventSubscriptionIdOnStopped !== undefined) { - eventsServerClient.stopListening(key, eventSubscriptionIdOnStopped, 'UiObject') - } + finalizeEventsServerClient() thisObject.container.eventHandler.stopListening(selfFocusEventSubscriptionId) thisObject.container.eventHandler.stopListening(selfNotFocusEventSubscriptionId) @@ -173,6 +168,19 @@ function newUiObject () { onRunningCallBackFunction = undefined } + function finalizeEventsServerClient () { + if (eventsServerClient !== undefined) { + let key = thisObject.payload.node.name + '-' + thisObject.payload.node.type + '-' + thisObject.payload.node.id + + if (eventSubscriptionIdOnRunning !== undefined) { + eventsServerClient.stopListening(key, eventSubscriptionIdOnRunning, 'UiObject') + } + if (eventSubscriptionIdOnStopped !== undefined) { + eventsServerClient.stopListening(key, eventSubscriptionIdOnStopped, 'UiObject') + } + } + } + function initialize (payload, menuItemsInitialValues) { thisObject.payload = payload @@ -750,14 +758,17 @@ function newUiObject () { } } - function run (callBackFunction) { + function run (pEventsServerClient, callBackFunction) { + finalizeEventsServerClient() + eventsServerClient = pEventsServerClient + /* We setup the circular progress bar. */ if (thisObject.circularProgressBar !== undefined) { thisObject.circularProgressBar.finalize() } thisObject.circularProgressBar = newCircularProgressBar() - thisObject.circularProgressBar.initialize(thisObject.payload) + thisObject.circularProgressBar.initialize(thisObject.payload, eventsServerClient) thisObject.circularProgressBar.fitFunction = thisObject.fitFunction thisObject.circularProgressBar.container = thisObject.container diff --git a/CanvasApp/Panels/Layer.js b/CanvasApp/Panels/Layer.js index bc1ffadb5..44e067063 100644 --- a/CanvasApp/Panels/Layer.js +++ b/CanvasApp/Panels/Layer.js @@ -20,6 +20,7 @@ function newLayer () { plotterTypeIcon: undefined, baseAssetIcon: undefined, quotedAssetIcon: undefined, + networkNode: undefined, checkStatusAtShutDown: checkStatusAtShutDown, physics: physics, draw: draw, @@ -128,6 +129,7 @@ function newLayer () { thisObject.plotterTypeIcon = undefined thisObject.baseAssetIcon = undefined thisObject.quotedAssetIcon = undefined + thisObject.networkNode = undefined } function initialize (callBackFunction) { @@ -151,9 +153,10 @@ function newLayer () { let functionLibraryProtocolNode = newProtocolNode() let lightingPath = '->Layer->' + - 'Data Product->Single Market Data->' + - 'Session Independent Data->Session Based Data->' + - 'Session Reference->Backtesting Session->Paper Trading Session->Fordward Testing Session->Live Trading Session->' + + 'Data Product->Single Market Data->Exchange Data Products->' + + 'Session Reference->Session Independent Data->Session Based Data->Exchange Sessions->Session Based Data->Data Storage->Network Node->' + + 'Data Storage->Network Node->' + + 'Backtesting Session->Paper Trading Session->Fordward Testing Session->Live Trading Session->' + 'Market->Market Base Asset->Asset->' + 'Market Quoted Asset->Asset->' + 'Exchange Markets->Crypto Exchange->' + @@ -186,6 +189,10 @@ function newLayer () { if (thisObject.definition.referenceParent.referenceParent === undefined) { return } if (thisObject.definition.referenceParent.referenceParent.parentNode === undefined) { return } if (thisObject.definition.referenceParent.referenceParent.parentNode.parentNode === undefined) { return } + if (thisObject.definition.referenceParent.parentNode.parentNode === undefined) { return } + if (thisObject.definition.referenceParent.parentNode.parentNode.parentNode === undefined) { return } + if (thisObject.definition.referenceParent.parentNode.parentNode.parentNode.parentNode === undefined) { return } + if (thisObject.definition.referenceParent.parentNode.parentNode.parentNode.parentNode.parentNode === undefined) { return } /* Lets listen to our own events to react when we have a Mouse Click */ onMouseClickEventSuscriptionId = thisObject.container.eventHandler.listenToEvent('onMouseClick', onMouseClick) @@ -226,6 +233,12 @@ function newLayer () { thisObject.baseAssetIcon = getIcon(thisObject.baseAsset) thisObject.quotedAssetIcon = getIcon(thisObject.quotedAsset) + if (thisObject.definition.referenceParent.parentNode.parentNode.parentNode.parentNode.type === 'Data Storage') { + thisObject.networkNode = thisObject.definition.referenceParent.parentNode.parentNode.parentNode.parentNode.parentNode + } else { + thisObject.networkNode = thisObject.definition.referenceParent.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode + } + function getIcon (node) { let nodeDefinition = APP_SCHEMA_MAP.get(node.type) let iconName diff --git a/CanvasApp/PostLoader.js b/CanvasApp/PostLoader.js index 0af816538..d47eb8add 100644 --- a/CanvasApp/PostLoader.js +++ b/CanvasApp/PostLoader.js @@ -1,6 +1,5 @@ let canvas let markets -let eventsServerClient let APP_SCHEMA_MAP = new Map() let APP_SCHEMA_ARRAY = [] @@ -23,9 +22,7 @@ function newDashboard () { function start () { try { setBrowserEvents() - - eventsServerClient = newEventsServerClient() - eventsServerClient.initialize(setUpAppSchema) + setUpAppSchema() function setUpAppSchema () { APP_SCHEMA_ARRAY = getAppSchema() diff --git a/CanvasApp/ProductStorage.js b/CanvasApp/ProductStorage.js index 4e0c4142a..68c76ef1b 100644 --- a/CanvasApp/ProductStorage.js +++ b/CanvasApp/ProductStorage.js @@ -74,7 +74,7 @@ function newProductStorage (name) { } } - function initialize (dataMine, bot, session, product, exchange, market, pDatetime, pTimeFrame, callBackFunction) { + function initialize (dataMine, bot, session, product, exchange, market, pDatetime, pTimeFrame, host, port, eventsServerClient, callBackFunction) { try { datetime = pDatetime timeFrame = pTimeFrame @@ -90,7 +90,7 @@ function newProductStorage (name) { dataSetsToLoad++ let marketFiles = newMarketFiles() - marketFiles.initialize(dataMine, bot, session, product, dataset, exchange, market, onMarketFileReady) + marketFiles.initialize(dataMine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onMarketFileReady) thisObject.marketFiles.push(marketFiles) } break @@ -99,7 +99,7 @@ function newProductStorage (name) { dataSetsToLoad++ let dailyFiles = newDailyFiles() - dailyFiles.initialize(dataMine, bot, session, product, dataset, exchange, market, pDatetime, pTimeFrame, onDailyFileReady) + dailyFiles.initialize(dataMine, bot, session, product, dataset, exchange, market, pDatetime, pTimeFrame, host, port, eventsServerClient, onDailyFileReady) thisObject.dailyFiles.push(dailyFiles) } break @@ -108,7 +108,7 @@ function newProductStorage (name) { dataSetsToLoad++ let singleFile = newSingleFile() - singleFile.initialize(dataMine, bot, session, product, dataset, exchange, market, onSingleFileReady) + singleFile.initialize(dataMine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onSingleFileReady) thisObject.singleFile.push(singleFile) } break @@ -117,7 +117,7 @@ function newProductStorage (name) { dataSetsToLoad++ let fileSequences = newFileSequence() - fileSequences.initialize(dataMine, bot, session, product, dataset, exchange, market, onFileSequenceReady) + fileSequences.initialize(dataMine, bot, session, product, dataset, exchange, market, host, port, eventsServerClient, onFileSequenceReady) thisObject.fileSequences.push(fileSequences) } break diff --git a/Files-Component/src/DailyFiles.js b/Files-Component/src/DailyFiles.js index faf199ce8..55cb27de9 100644 --- a/Files-Component/src/DailyFiles.js +++ b/Files-Component/src/DailyFiles.js @@ -45,14 +45,14 @@ function newDailyFiles () { } } - function initialize (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pDatetime, pTimeFrame, callBackFunction) { + function initialize (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pDatetime, pTimeFrame, pHost, pPort, pEventsServerClient, callBackFunction) { try { callBackWhenFileReceived = callBackFunction let exchange = pExchange fileCloud = newFileCloud() - fileCloud.initialize(pBot) + fileCloud.initialize(pBot, pHost, pPort) /* Some Validations */ if (pDataset.code.validTimeFrames === undefined) { @@ -114,7 +114,7 @@ function newDailyFiles () { if (pDataset.code.validTimeFrames.includes(periodName) === true) { let fileCursor = newFileCursor() fileCursor.eventHandler = thisObject.eventHandler // We share our event handler with each file cursor, so that they can raise events there when files are changed.s - fileCursor.initialize(fileCloud, pDataMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, periodName, periodTime, pDatetime, pTimeFrame, beginDateRange, endDateRange, onInitialized) + fileCursor.initialize(fileCloud, pDataMine, pBot, pSession, pProduct, pDataset, exchange, pMarket, periodName, periodTime, pDatetime, pTimeFrame, beginDateRange, endDateRange, pEventsServerClient, onInitialized) function onInitialized (err) { try { switch (err.result) { diff --git a/Files-Component/src/FileCloud.js b/Files-Component/src/FileCloud.js index 4ee129964..051705797 100644 --- a/Files-Component/src/FileCloud.js +++ b/Files-Component/src/FileCloud.js @@ -17,12 +17,12 @@ function newFileCloud () { initialize: initialize } - let blobService + let fileStorage return thisObject - function initialize (pBot) { - blobService = newFileStorage() + function initialize (pBot, pHost, pPort) { + fileStorage = newFileStorage(pHost, pPort) } function getFile (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pPeriodName, pDatetime, pSequence, pDataRange, callBackFunction) { @@ -121,7 +121,7 @@ function newFileCloud () { if (INFO_LOG === true) { logger.write('[INFO] getFile -> getFileRecursively -> filePath = ' + filePath) } if (INFO_LOG === true) { logger.write('[INFO] getFile -> getFileRecursively -> fileName = ' + fileName) } - blobService.getBlobToText(filePath + '/' + fileName, undefined, onFileReceived) + fileStorage.getFileFromHost(filePath + '/' + fileName, onFileReceived) function onFileReceived (err, text, response) { try { diff --git a/Files-Component/src/FileCursor.js b/Files-Component/src/FileCursor.js index 88c1463e1..29ddb900e 100644 --- a/Files-Component/src/FileCursor.js +++ b/Files-Component/src/FileCursor.js @@ -34,6 +34,7 @@ function newFileCursor () { let timeFrame let beginDateRange let endDateRange + let eventsServerClient let finalized = false @@ -61,6 +62,7 @@ function newFileCursor () { timeFrame = undefined beginDateRange = undefined endDateRange = undefined + eventsServerClient = undefined thisObject.files = undefined cursorDate = undefined @@ -73,7 +75,23 @@ function newFileCursor () { } } - function initialize (pFileCloud, pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, pPeriodName, pTimeFrame, pCursorDate, pCurrentTimeFrame, pBeginDateRange, pEndDateRange, callBackFunction) { + function initialize ( + pFileCloud, + pDataMine, + pBot, + pSession, + pProduct, + pDataset, + pExchange, + pMarket, + pPeriodName, + pTimeFrame, + pCursorDate, + pCurrentTimeFrame, + pBeginDateRange, + pEndDateRange, + pEventsServerClient, + callBackFunction) { try { market = pMarket exchange = pExchange @@ -88,6 +106,7 @@ function newFileCursor () { timeFrame = pTimeFrame beginDateRange = pBeginDateRange endDateRange = pEndDateRange + eventsServerClient = pEventsServerClient let key = dataMine.code.codeName + '-' + bot.code.codeName + '-' + product.code.codeName + '-' + dataset.code.codeName + '-' + exchange.name + '-' + market.baseAsset + '/' + market.quotedAsset let callerId = key + '-' + periodName + newUniqueId() diff --git a/Files-Component/src/FileSequence.js b/Files-Component/src/FileSequence.js index feedf0b32..f14de19f4 100644 --- a/Files-Component/src/FileSequence.js +++ b/Files-Component/src/FileSequence.js @@ -32,6 +32,7 @@ function newFileSequence () { let eventSubscriptionIdDatasetUpdated let callerId + let eventsServerClient return thisObject @@ -52,6 +53,7 @@ function newFileSequence () { session = undefined dataset = undefined product = undefined + eventsServerClient = undefined finalized = true } catch (err) { @@ -59,7 +61,18 @@ function newFileSequence () { } } - function initialize (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, callBackFunction) { + function initialize ( + pDataMine, + pBot, + pSession, + pProduct, + pDataset, + pExchange, + pMarket, + pHost, + pPort, + pEventsServerClient, + callBackFunction) { try { exchange = pExchange market = pMarket @@ -68,9 +81,10 @@ function newFileSequence () { session = pSession dataset = pDataset product = pProduct + eventsServerClient = pEventsServerClient fileCloud = newFileCloud() - fileCloud.initialize(bot) + fileCloud.initialize(bot, pHost, pPort) callerId = newUniqueId() diff --git a/Files-Component/src/FileStorage.js b/Files-Component/src/FileStorage.js index bdd833546..6bd1d1883 100644 --- a/Files-Component/src/FileStorage.js +++ b/Files-Component/src/FileStorage.js @@ -1,4 +1,4 @@ -function newFileStorage () { +function newFileStorage (host, port) { const MODULE_NAME = 'File Storage' const INFO_LOG = false const logger = newWebDebugLog() @@ -24,20 +24,25 @@ function newFileStorage () { ] let thisObject = { - getBlobToText: getBlobToText + getFileFromHost: getFileFromHost } return thisObject - async function getBlobToText (filePath, host, callBackFunction, pathComplete) { + async function getFileFromHost (filePath, callBackFunction, pathComplete) { try { - if (INFO_LOG === true) { logger.write('[INFO] getBlobToText -> Entering function.') } + if (INFO_LOG === true) { logger.write('[INFO] getFileFromHost -> Entering function.') } let folder = '' if (pathComplete === false || pathComplete === undefined) { folder = 'Storage/' } - callServer(undefined, folder + filePath, (response, fileContent) => { + let url = folder + filePath + if (host !== undefined) { + url = 'http://' + host + ':' + port + '/' + folder + filePath + } + + callServer(undefined, url, (response, fileContent) => { if (response.result === GLOBAL.DEFAULT_OK_RESPONSE.result) { callBackFunction(GLOBAL.DEFAULT_OK_RESPONSE, fileContent) } else { @@ -48,7 +53,7 @@ function newFileStorage () { if (verifyRetry(err.code) && currentRetry < MAX_RETRY) { currentRetry++ if (INFO_LOG === true) { console.log('[INFO] getTextFile -> Retrying connection to the server because received error: ' + err.code + '. Retry #: ' + currentRetry) } - getBlobToText(filePath, host, callBackFunction) + getFileFromHost(filePath, callBackFunction) } else if (err.message === 'Request aborted') { let err = { code: 'The specified key does not exist.' } callBackFunction(err) diff --git a/Files-Component/src/MarketFiles.js b/Files-Component/src/MarketFiles.js index ec1a45ee2..666389d08 100644 --- a/Files-Component/src/MarketFiles.js +++ b/Files-Component/src/MarketFiles.js @@ -37,6 +37,7 @@ function newMarketFiles () { let finalized = false let eventSubscriptionIdDatasetUpdated = [] + let eventsServerClient return thisObject @@ -60,6 +61,7 @@ function newMarketFiles () { dataset = undefined product = undefined periodName = undefined + eventsServerClient = undefined finalized = true } catch (err) { @@ -67,7 +69,18 @@ function newMarketFiles () { } } - function initialize (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, callBackFunction) { + function initialize ( + pDataMine, + pBot, + pSession, + pProduct, + pDataset, + pExchange, + pMarket, + pHost, + pPort, + pEventsServerClient, + callBackFunction) { try { exchange = pExchange market = pMarket @@ -76,9 +89,10 @@ function newMarketFiles () { session = pSession dataset = pDataset product = pProduct + eventsServerClient = pEventsServerClient fileCloud = newFileCloud() - fileCloud.initialize(pBot) + fileCloud.initialize(pBot, pHost, pPort) /* Some Validations */ if (dataset.code.validTimeFrames === undefined) { diff --git a/Files-Component/src/SingleFile.js b/Files-Component/src/SingleFile.js index ba9971e6f..17d2542de 100644 --- a/Files-Component/src/SingleFile.js +++ b/Files-Component/src/SingleFile.js @@ -16,7 +16,18 @@ function newSingleFile () { return thisObject - function initialize (pDataMine, pBot, pSession, pProduct, pDataset, pExchange, pMarket, callBackFunction) { + function initialize ( + pDataMine, + pBot, + pSession, + pProduct, + pDataset, + pExchange, + pMarket, + pHost, + pPort, + pEventsServerClient, + callBackFunction) { try { if (INFO_LOG === true) { logger.write('[INFO] initialize -> Entering function.') } if (INFO_LOG === true) { logger.write('[INFO] initialize -> key = ' + pDataMine.code.codeName + '-' + pBot.code.codeName + '-' + pProduct.code.codeName) } @@ -24,7 +35,7 @@ function newSingleFile () { let exchange = pExchange fileCloud = newFileCloud() - fileCloud.initialize(pBot) + fileCloud.initialize(pBot, pHost, pPort) /* Now we will get the file */