Advertisement
profezzional

dbData.controller.js

Nov 4th, 2017
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const ObjectID = require('mongoose').Types.ObjectId;
  2. const dbData = require('../models/dbData.model');
  3.  
  4. // THE BIG STACKS
  5. var masterEventQueue = [];
  6. var eventsToPush = [];
  7. var isProcessingQueue = false;
  8. var recursionSafetyCount = 0;
  9.  
  10. var debug = true;
  11.  
  12. module.exports = {
  13.     getDbData: getDbData,
  14.     getSampleDbData: getSampleDbData,
  15.     processEvent: processEvent,
  16.     processSocketMessage: processSocketMessage
  17. };
  18.  
  19.  
  20.  
  21. function processSocketMessage(io, socket) {
  22.     console.log('a user connected');
  23.  
  24.     if ((socket.handshake.session.passport == null || socket.handshake.session.passport.user == null) && (socket.handshake.headers.origin != 'http://localhost:4200')) {
  25.         socket.disconnect();
  26.         console.log('Socket Auth Error - Disconnecting User')
  27.     }
  28.  
  29.     socket.on('disconnect', function () {
  30.         console.log('user disconnected');
  31.     });
  32.  
  33.     // retrieve sample dbData object
  34.     socket.on('request-sample-dbData', function (type) {
  35.         console.log('Request dbData of type ' + type);
  36.  
  37.         getSampleDbData().then(function (dbDataObj) {
  38.                 if (!dbDataObj) {
  39.                     console.log('Error did not find a matching dbData');
  40.                 }
  41.                 dbDataObj.server = true;
  42.                 io.emit('receive-sample-dbData', {
  43.                     source: dbDataObj[1],
  44.                     target: dbDataObj[0]
  45.                 });
  46.             });
  47.     });
  48.  
  49.     socket.on('requestCompassCurrentProjectsList', function () {
  50.         console.log('Received request for current projects in Compass');
  51.  
  52.         // CONNECT TO COMPASS AND GET PROJECTS LIST HERE
  53.  
  54.         //io.emit('receiveCompassCurrentProjectsList', socket);
  55.  
  56.         //getCompassCurrentProjects().then(function (projectsList) {
  57.         //    if (!projectsList) {
  58.         //        console.log('Error: did not fetch projects list');
  59.         //    } else {
  60.         //        projectsList.server = true;
  61.  
  62.         //        io.emit('receiveCompassCurrentProjectsList', {
  63.         //            projectsList: projectsList
  64.         //        });
  65.         //    }
  66.         //});
  67.  
  68.         // temp sample compass projects data
  69.         // TODO: add other project info (client, facility, subfacility, etc....timestamps?)
  70.         io.emit('receiveCompassCurrentProjectsList', {
  71.             numProjects: 3,
  72.             list: [
  73.                 {
  74.                     _id: '59361424e67f770b99e45482',
  75.                     name: 'Test Project 1',
  76.                     state: 'Current',
  77.                     system: 'Star PA',
  78.                     version: '1.3.5',
  79.                     vendor: 'McKesson',
  80.                     hasMappingServiceType: true,
  81.                     referenceNum: 1234
  82.                 },
  83.                 {
  84.                     _id: '59361424e67f770b99e45483',
  85.                     name: 'Test Project 2',
  86.                     state: 'Current',
  87.                     system: 'Eclipsys SDK PA',
  88.                     version: '5.7.0',
  89.                     vendor: 'Allscripts',
  90.                     hasMappingServiceType: true,
  91.                     referenceNum: 1235
  92.                 },
  93.                 {
  94.                     _id: '59361424e67f770b99e45484',
  95.                     name: 'Test Project 3',
  96.                     state: 'Current',
  97.                     system: 'Invision PA',
  98.                     version: '4.7.1',
  99.                     vendor: 'Siemens',
  100.                     hasMappingServiceType: true,
  101.                     referenceNum: 1236
  102.                 }
  103.             ]
  104.         });
  105.  
  106.  
  107.     });
  108.  
  109.     //Update DB Field
  110.     socket.on('state-change', function (event) {
  111.         event.fromServer = true;
  112.         event.hasID = false;
  113.         //Emit event to all clients who are currently connected
  114.         // By default, clients should ignore 'add' events from the server that have 'hasID = false'
  115.         if (event != null && event.action != null && event.action != 'add') {
  116.             socket.broadcast.emit('state-has-changed', event);
  117.         }
  118.         //Send Event to Queue for Processing
  119.         processEvent(event, socket, io);
  120.     });
  121. }
  122.  
  123. function getDbData(req, res) {
  124.     if (!req.user) {
  125.         response.redirect('/login');
  126.     } else {
  127.         dbData.findOne({ _id: req.params.id }, function (err, dbDataObj) {
  128.             if (err) {
  129.                 console.log('Error while retrieving dbData from database');
  130.                 return res.status(500).send('Internal Errors, check server logs!');
  131.             }
  132.             if (!dbDataObj) {
  133.                 console.log('Error did not find a matching dbData');
  134.                 return res.status(500).send('Internal Errors, check server logs!');
  135.             }
  136.             return res.json(dbDataObj);
  137.         });
  138.     }
  139. }
  140.  
  141. function getSampleDbData() {
  142.     return dbData.find({}).exec(); // only works with 2 docs in the collection; this will crash & burn if theres multiple documents
  143. }
  144.  
  145. function processEvent(event, socket, io) {
  146.     //Basic Event Validation
  147.     if (event == null) {
  148.         // Error, either event or event info doesn't exist.
  149.         console.log('ERROR! Received a bad event, please check formatting of event');
  150.         return false;
  151.     } else {
  152.         event.pushedToQueue = Date.now();
  153.         masterEventQueue.push(event);
  154.         var startTime = Date.now();
  155.         processQueue(socket, io).then(function (qResult) {
  156.             if (!qResult) {
  157.                 if (debug) { console.log(qResult); }
  158.                 console.log('Queue is already processing...');
  159.                 return Promise.resolve(true);
  160.             }
  161.             var endTime = Date.now();
  162.             console.log('Queue completed running in ' + (endTime - startTime) + ' milliseconds!\r\n');
  163.         });
  164.     }
  165. }
  166.  
  167. function executeEvent(event) {
  168.     //THE MEGA SWITCH (not by nintendo)
  169.     // This is where we decide how to handle all the different events
  170.     // This function is probably gonna be huge lol
  171.  
  172.     function getField(doc, data) {
  173.         if (doc == null || data == null) {
  174.             console.log(doc);
  175.             console.log(data);
  176.             console.log('^^Doc or Data Null!');
  177.             return false;
  178.         }
  179.         if (data.hasOwnProperty('dbSchema') && data.hasOwnProperty('dbTable') && data.hasOwnProperty('_id')) {
  180.             // Should be able to properly search and find field!
  181.             if (debug) { console.log('Found field named ' + doc.dbSchemas.id(data.dbSchema._id).dbTables.id(data.dbTable._id).dbFields.id(data._id).name + ' | getField()') };
  182.             return doc.dbSchemas.id(data.dbSchema._id).dbTables.id(data.dbTable._id).dbFields.id(data._id);
  183.         }
  184.         else {
  185.             //Received invalid data
  186.             console.log('findField() received invalid data');
  187.             return null;
  188.         }
  189.     }
  190.     function getTable(doc, data) {
  191.         if (doc == null || data == null) {
  192.             console.log(doc);
  193.             console.log(data);
  194.             console.log('^^Doc or Data Null!');
  195.             return false;
  196.         }
  197.         if (data.hasOwnProperty('dbTable')) {
  198.             if (data.hasOwnProperty('dbSchema')) {
  199.                 // Should be able to properly search and find field!
  200.                 if (debug) {
  201.                     console.log('Found table named ' + doc.dbSchemas.id(data.dbSchema._id).dbTables.id(data.dbTable._id).name + ' | getTable()')
  202.                 }
  203.                 ;
  204.                 return doc.dbSchemas.id(data.dbSchema._id).dbTables.id(data.dbTable._id);
  205.             }
  206.             else {
  207.                 //Received invalid data
  208.                 console.log('findTable() received invalid data');
  209.                 return null;
  210.             }
  211.         }
  212.         else {
  213.             if (data.hasOwnProperty('dbSchema') && data.hasOwnProperty('_id')) {
  214.                 // Should be able to properly search and find field!
  215.                 if (debug) {
  216.                     console.log('Found table named ' + doc.dbSchemas.id(data.dbSchema._id).dbTables.id(data._id).name + ' | getTable()')
  217.                 }
  218.                 ;
  219.                 return doc.dbSchemas.id(data.dbSchema._id).dbTables.id(data._id);
  220.             }
  221.             else {
  222.                 //Received invalid data
  223.                 console.log('findTable() received invalid data');
  224.                 return null;
  225.             }
  226.         }
  227.     }
  228.     function getSchema(doc, data) {
  229.         if (doc == null || data == null) {
  230.             console.log(doc);
  231.             console.log(data);
  232.             console.log('^^Doc or Data Null!');
  233.             return false;
  234.         }
  235.         if (data.hasOwnProperty('dbSchema')) {
  236.             if (data.hasOwnProperty('dbData')) {
  237.                 // Should be able to properly search and find field!
  238.                 if (debug) { console.log('Found Schema named ' + doc.dbSchemas.id(data.dbSchema._id).name + ' | getSchema()') };
  239.                 return doc.dbSchemas.id(data.dbSchema._id);
  240.             }
  241.  
  242.             else {
  243.                 //Received invalid data
  244.                 console.log('findSchema() received invalid data');
  245.                 return null;
  246.             }
  247.         }
  248.         else {
  249.             if (data.hasOwnProperty('dbData')) {
  250.                 // Should be able to properly search and find field!
  251.                 if (debug) { console.log('Found Schema named ' + doc.dbSchemas.id(data._id).name + ' | getSchema()') };
  252.                 return doc.dbSchemas.id(data._id);
  253.             }
  254.  
  255.             else {
  256.                 //Received invalid data
  257.                 console.log('findSchema() received invalid data');
  258.                 return null;
  259.             }
  260.         }
  261.     }
  262.     function getDbData(data) {
  263.         if (data == null) {
  264.             console.log(data);
  265.             console.log('Data Null!');
  266.             return Promise.resolve(false);
  267.         }
  268.         if (data.hasOwnProperty('dbData')) {
  269.             if (debug) { console.log('Returned promise for query to get dbData (id: ' + data.dbData._id + ') | getDbData()') };
  270.             return dbData.findById(data.dbData._id).exec();
  271.         }
  272.         else {
  273.             console.log('getDbData() received invalid data');
  274.             return Promise.resolve(false);
  275.         }
  276.     }
  277.  
  278.     // CATCH event.action that is not equal to map
  279.     switch (event.action) {
  280.         case 'map':
  281.             switch (event.mappingAction) {
  282.                 case 'addMap':
  283.                     if (debug) { console.log('Event type: ' + event.action); }
  284.  
  285.                     /**
  286.                      * =============== ADD MAP ===============
  287.                      * 1. Find senderOrigin (TARGET SIDE)
  288.                      * 2. Append mappingObject to the `mappings` property of returned doc from #1 and save it
  289.                      * ----STEPS 3 & 4 DIRECT TYPE ONLY, LOOKUPS STOP AFTER STEP 2----
  290.                      * 3. Find `mappingObject.link` (SOURCE SIDE)
  291.                      * 4. Make new mappingObject that links back to `senderOrigin` and append it to the mappings propert from #3
  292.                      *
  293.                      */
  294.  
  295.                     // Step 1
  296.                     return getDbData(event.senderOrigin)
  297.                         .then(function (targetDbData) {
  298.                             if (!targetDbData) { if (debug) { console.log('Error in getting dbData document'); } return Promise.resolve(false); }
  299.                             // Step 2
  300.                             var targetField = getField(targetDbData, event.senderOrigin);
  301.                             targetField.mappings.push(event.info.mappingObject);
  302.                             if (debug) { console.log('Pushed new mapping object onto sender.  New mappings array for sender: '); console.log(targetField.mappings); }
  303.                             // Step 3
  304.                             return targetDbData.save();
  305.                         })
  306.                         .then(function (saveTargetResult) {
  307.                             if (!saveTargetResult) { if (debug) { console.log('Failed to Save Sender Document'); } return Promise.resolve(false); }
  308.                             //Need to decide if direct mapping, otherwise skip steps 4 and 5
  309.                             if (event.info.mappingObject.type !== 'direct') {
  310.                                 if (debug) { console.log('Mapping type is not direct, skipping SOURCE SIDE steps (Ignore next few errors)') }
  311.                                 return Promise.resolve(false);
  312.                             }
  313.                             // Step 4
  314.                             //Is direct, go ahead and do SOURCE SIDE logic
  315.                             return getDbData(event.info.mappingObject.link);
  316.  
  317.                         })
  318.                         .then(function (sourceDbData) {
  319.                             if (!sourceDbData) { if (debug) { console.log('Possible error in getting source DbData (or skipping step)'); } return Promise.resolve(false); }
  320.                             var sourceField = getField(sourceDbData, event.info.mappingObject.link);
  321.                             sourceField.mappings.push({
  322.                                 type: 'direct',
  323.                                 link: event.senderOrigin,
  324.                                 separator: ''
  325.                             });
  326.                             if (debug) { console.log('Pushed new mapping object onto source object.  New mappings array for source: '); console.log(sourceField.mappings); }
  327.                             return sourceDbData.save();
  328.                         })
  329.                         .then(function (saveSourceResult) {
  330.                             if (!saveSourceResult) { if (debug) { console.log('Failed to Save Sender Document or Skipping Step'); } return Promise.resolve(false); }
  331.                             // Save was successful
  332.                             return Promise.resolve(true);
  333.                         })
  334.                         .then(function (endResult) {
  335.                             if (debug) { console.log('Completed Add Map logic.  Promise is returning true!'); }
  336.                             return Promise.resolve(true);
  337.                         })
  338.                         .catch(function (err) {
  339.                             if (debug) { console.log('Add Map | Promise catch for uncaught errors.  Error: ' + err); }
  340.                             Promise.resolve(false);
  341.                         });
  342.                     break;
  343.                 case 'removeMap':
  344.                     if (debug) { console.log('Event type: ' + event.action); }
  345.  
  346.                     //=============== REMOVE MAP ===============
  347.                     // 1. Find senderOrigin (TARGET SIDE)
  348.                     // 2. Remove from #1 the mappings[mappingIndex]
  349.                     //----STEPS 3 & 4 Need to be repeated for each KEY in a lookup ----
  350.                     // 3. Find `mappingObject.link` (SOURCE SIDE)
  351.                     // 4. Loop through all mappings from #3 to find and remove link to senderOrigin
  352.  
  353.                     // Step 1
  354.                     return getDbData(event.senderOrigin)
  355.                         .then(function (targetDbData) {
  356.                             if (!targetDbData) { if (debug) { console.log('Error in getting dbData document'); } return Promise.resolve(false); }
  357.                             // Step 2
  358.                             var targetField = getField(targetDbData, event.senderOrigin);
  359.                             targetField.mappings.splice(event.info.mappingIndex, 1);
  360.                             if (debug) { console.log('Removed mapping from target side at mapping index: ' + event.info.mappingObject + '.  Revised mappings array for sender: '); console.log(targetField.mappings); }
  361.                             // Step 3
  362.                             return targetDbData.save();
  363.                         })
  364.                         .then(function (saveTargetResult) {
  365.                             if (!saveTargetResult) { if (debug) { console.log('Failed to Save Sender Document'); } return Promise.resolve(false); }
  366.                             // Step 4
  367.                             //If direct, need to use mappingObject.link, if lookup need to figure out which keys have values
  368.                             //  and pick one to use to get the DbData property
  369.                             if (event.info.mappingObject.type === 'direct') {
  370.                                 return getDbData(event.info.mappingObject.link);
  371.                             }
  372.                             // Lookup Logic
  373.                             if (event.info.mappingObject.link[0].hasOwnProperty('sourceFK')) {
  374.                                 return getDbData(event.info.mappingObject.link[0].sourceFK);
  375.                             }
  376.                             else if (event.info.mappingObject.link[0].hasOwnProperty('lookupPK')) {
  377.                                 return getDbData(event.info.mappingObject.link[0].lookupPK);
  378.                             }
  379.                             else if (event.info.mappingObject.link[0].hasOwnProperty('lookupFK')) {
  380.                                 return getDbData(event.info.mappingObject.link[0].lookupFK);
  381.                             }
  382.                             else {
  383.                                 if (debug) { console.log('Failed to find a dbData ID to use from one of the lookups.  Perhaps deleting an empty mapping?'); }
  384.                                 return Promise.resolve(false);
  385.                             }
  386.                         })
  387.                         .then(function (sourceDbData) {
  388.                             if (!sourceDbData) { if (debug) { console.log('Error in getting source DbData OR No mappings to delete from source.'); } return Promise.resolve(false); }
  389.                             var fieldsToScan = [];
  390.                             if (event.info.mappingObject.type === 'direct') {
  391.                                 fieldsToScan.push(getField(sourceDbData, event.info.mappingObject.link));
  392.                             }
  393.                             else {
  394.                                 if (event.info.mappingObject.link[0].hasOwnProperty('sourceFK')) {
  395.                                     fieldsToScan.push(getField(sourceDbData, event.info.mappingObject.link[0].sourceFK));
  396.                                 }
  397.                                 if (event.info.mappingObject.link[0].hasOwnProperty('lookupPK')) {
  398.                                     fieldsToScan.push(getField(sourceDbData, event.info.mappingObject.link[0].lookupPK));
  399.                                 }
  400.                                 if (event.info.mappingObject.link[0].hasOwnProperty('lookupFK')) {
  401.                                     fieldsToScan.push(getField(sourceDbData, event.info.mappingObject.link[0].lookupFK));
  402.                                 }
  403.                             }
  404.  
  405.                             for (var i = 0; i < fieldsToScan.length; i++) {
  406.                                 var sourceField = fieldsToScan[i];
  407.                                 //Step 4
  408.                                 for (var j = 0; j < sourceField.mappings.length; j++) {
  409.                                     var linkID = sourceField.mappings[i].link._id;
  410.                                     if (linkID == event.senderOrigin._id) {
  411.                                         //Found a match
  412.                                         if (debug) { console.log('Found a matched mapping, removing from source side'); }
  413.                                         sourceField.mappings.splice(j, 1);
  414.                                         break;
  415.                                     }
  416.                                 }
  417.                             }
  418.  
  419.                             if (debug) { console.log('Finished looping through source fields to modify'); }
  420.                             return sourceDbData.save();
  421.                         })
  422.                         .then(function (saveSourceResult) {
  423.                             if (!saveSourceResult) { if (debug) { console.log('Failed to Save Sender Document or Skipping source side due to nothing needing removed.'); } return Promise.resolve(false); }
  424.                             // Save was successful
  425.                             return Promise.resolve(true);
  426.                         })
  427.                         .then(function (endResult) {
  428.                             if (debug) { console.log('Completed Remove Map logic.  Promise is returning true!'); }
  429.                             return Promise.resolve(true);
  430.                         })
  431.                         .catch(function (err) {
  432.                             if (debug) { console.log('Remove Map | Promise catch for uncaught errors.  Error: ' + err); }
  433.                             Promise.resolve(false);
  434.                         });
  435.                     break;
  436.                 case 'editSeparator':
  437.                     if (debug) { console.log('Event type: ' + event.action); }
  438.  
  439.                     //=============== EDIT SEPARATOR ===============
  440.                     // 1. Find senderOrigin (TARGET SIDE)
  441.                     // 2. Overwrite separator at mappings[mappingIndex] from #1
  442.  
  443.                     // Step 1
  444.                     return getDbData(event.senderOrigin)
  445.                         .then(function (targetDbData) {
  446.                             if (!targetDbData) { if (debug) { console.log('Error in getting dbData document'); } return Promise.resolve(false); }
  447.                             // Step 2
  448.                             var targetField = getField(targetDbData, event.senderOrigin);
  449.                             // Must mark as changed, since Mongoose doesn't autodetect the change
  450.                             targetField.mappings[event.info.mappingIndex].separator = event.info.separatorValue;
  451.                             targetField.markModified('mappings.' + event.info.mappingIndex + '.separator');
  452.  
  453.  
  454.                             if (debug) { console.log('Edited separator value: '); console.log(targetField.mappings[event.info.mappingIndex].separator); }
  455.                             // Step 3
  456.                             return targetDbData.save();
  457.                         })
  458.                         .then(function (saveTargetResult) {
  459.                             if (!saveTargetResult) { if (debug) { console.log('Failed to Save Sender Document'); } return Promise.resolve(false); }
  460.                             // Save was successful
  461.                             return Promise.resolve(true);
  462.                         })
  463.                         .then(function (endResult) {
  464.                             if (debug) { console.log('Completed Edit Separator logic.  Promise is returning true!'); }
  465.                             return Promise.resolve(true);
  466.                         })
  467.                         .catch(function (err) {
  468.                             if (debug) { console.log('Edit Separator | Promise catch for uncaught errors.  Error: ' + err); }
  469.                             Promise.resolve(false);
  470.                         });
  471.                     break;
  472.                 case 'addLevel':
  473.                     if (debug) { console.log('Event type: ' + event.action); }
  474.  
  475.                     //=============== ADD LEVEL ===============
  476.                     // 1. Find senderOrigin (TARGET SIDE)
  477.                     // 2. Override mappings[mappingIndex] of #1 with mappingObject
  478.  
  479.                     // Step 1
  480.                     return getDbData(event.senderOrigin)
  481.                         .then(function (targetDbData) {
  482.                             if (!targetDbData) { if (debug) { console.log('Error in getting dbData document'); } return Promise.resolve(false); }
  483.                             // Step 2
  484.                             var targetField = getField(targetDbData, event.senderOrigin);
  485.                             targetField.mappings[event.info.mappingIndex] = event.info.mappingObject;
  486.                             //Marking field as modified for the DB
  487.                             targetField.markModified('mappings.' + event.info.mappingIndex);
  488.                             if (debug) { console.log('Overwrote target side mapping at index ' + event.info.mappingIndex + ': '); console.log(targetField.mappings); }
  489.                             // Step 3
  490.                             return targetDbData.save();
  491.                         })
  492.                         .then(function (saveTargetResult) {
  493.                             if (!saveTargetResult) { if (debug) { console.log('Failed to Save Sender Document'); } return Promise.resolve(false); }
  494.                             // Save was successful
  495.                             return Promise.resolve(true);
  496.                         })
  497.                         .then(function (endResult) {
  498.                             if (debug) { console.log('Completed Add Level logic.  Promise is returning true!'); }
  499.                             return Promise.resolve(true);
  500.                         })
  501.                         .catch(function (err) {
  502.                             if (debug) { console.log('Add Level | Promise catch for uncaught errors.  Error: ' + err); }
  503.                             Promise.resolve(false);
  504.                         });
  505.                     break;
  506.                 case 'removeLevel':
  507.                     if (debug) { console.log('Event type: ' + event.action); }
  508.  
  509.                     //=============== Remove Level ===============
  510.                     // 1. Loop through all keys in levelObject
  511.                     // 2. For each, find source field (SOURCE SIDE)
  512.                     // 3. Loop through and remove any mappings that link back to senderOrigin
  513.                     // 4. Find senderOrigin (TARGET SIDE)
  514.                     // 5. Remove level from mapping at mappings[mappingIndex][levelIndex]
  515.  
  516.  
  517.                     //First, need to get a dbData object from one of the lookups...
  518.                     // Lookup Logic
  519.                     var tempObjForData;
  520.                     if (event.info.levelObject.hasOwnProperty('sourceFK')) {
  521.                         tempObjForData = event.info.levelObject.sourceFK;
  522.                     }
  523.                     else if (event.info.levelObject.hasOwnProperty('lookupPK')) {
  524.                         tempObjForData = event.info.levelObject.lookupPK;
  525.                     }
  526.                     else if (event.info.levelObject.hasOwnProperty('lookupFK')) {
  527.                         tempObjForData = event.info.levelObject.lookupFK;
  528.                     }
  529.                     else {
  530.                         if (debug) { console.log('Failed to find a dbData ID to use from one of the lookups'); }
  531.                         return Promise.resolve(false);
  532.                     }
  533.  
  534.                     // Step 1
  535.                     return getDbData(tempObjForData)
  536.                         .then(function (sourceDbData) {
  537.                             if (!sourceDbData) { if (debug) { console.log('Error in getting dbData document'); } return Promise.resolve(false); }
  538.                             //Looping through keys to get field objects.
  539.                             var listOfSourceLookups = [];
  540.                             // Step 2
  541.                             // EXCLUDE Source FK ONLY if the level index is greater than 0, this means it is already taken care of
  542.                             // by the previous lookup FK
  543.  
  544.                             if (event.info.levelIndex < 1 && event.info.levelObject.hasOwnProperty('sourceFK')) {
  545.                                 listOfSourceLookups.push(getField(sourceDbData, event.info.levelObject.sourceFK));
  546.                             }
  547.                             if (event.info.levelObject.hasOwnProperty('lookupPK')) {
  548.                                 listOfSourceLookups.push(getField(sourceDbData, event.info.levelObject.lookupPK));
  549.                             }
  550.                             if (event.info.levelObject.hasOwnProperty('lookupFK')) {
  551.                                 listOfSourceLookups.push(getField(sourceDbData, event.info.levelObject.lookupFK));
  552.                             }
  553.                             // Step 3
  554.                             for (var i = 0; i < listOfSourceLookups.length; i++) {
  555.                                 var sourceField = listOfSourceLookups[i];
  556.                                 for (var j = 0; j < sourceField.mappings.length; j++) {
  557.                                     var linkID = sourceField.mappings[j].link._id;
  558.                                     if (linkID == event.senderOrigin._id) {
  559.                                         //Found a match
  560.                                         if (debug) { console.log('Found a matched mapping, removing from source side'); }
  561.                                         sourceField.mappings.splice(j, 1);
  562.                                         //Marking field as modified for the DB
  563.                                         sourceField.markModified('mappings.' + j);
  564.                                     }
  565.                                 }
  566.                             }
  567.                             if (debug) { console.log('Finished looping through source fields to modify'); }
  568.                             return sourceDbData.save();
  569.                         })
  570.                         .then(function (saveSourceResult) {
  571.                             if (!saveSourceResult) { if (debug) { console.log('Failed to Save Source Document'); } return Promise.resolve(false); }
  572.                             // Step 4
  573.                             return getDbData(event.senderOrigin);
  574.                         })
  575.                         .then(function (targetDbData) {
  576.                             if (!targetDbData) { if (debug) { console.log('Error in getting sender DbData'); } return Promise.resolve(false); }
  577.                             var targetField = getField(targetDbData, event.senderOrigin);
  578.                             targetField.mappings[event.info.mappingIndex].link.splice(event.info.levelIndex, 1);
  579.                             //Marking field as modified for the DB
  580.                             targetField.markModified('mappings.' + event.info.mappingIndex + '.link');
  581.                             if (debug) { console.log('Removed level object from target side.  New mapping array for target: '); console.log(targetField.mappings); }
  582.                             return targetDbData.save();
  583.                         })
  584.                         .then(function (saveTargetResult) {
  585.                             if (!saveTargetResult) { if (debug) { console.log('Failed to Save Target Document'); } return Promise.resolve(false); }
  586.                             // Save was successful
  587.                             return Promise.resolve(true);
  588.                         })
  589.                         .then(function (endResult) {
  590.                             if (debug) { console.log('Completed Remove Level logic.  Promise is returning true!'); }
  591.                             return Promise.resolve(true);
  592.                         })
  593.                         .catch(function (err) {
  594.                             if (debug) { console.log('Remove Level | Promise catch for uncaught errors.  Error: ' + err); }
  595.                             Promise.resolve(false);
  596.                         });
  597.                     break;
  598.                 case 'editLevel':
  599.                     if (debug) { console.log('Event type: ' + event.action); }
  600.  
  601.                     //=============== Edit Level ===============
  602.                     // 1. Find previousKeyValue (SOURCE SIDE)
  603.                     // 2. Remove old mapping linked to senderOrigin
  604.                     // 2.5 If new field is empty, removing, otherwise editing/updating
  605.                     // 3. Add new mapping linked to senderOrigin
  606.                     // 4. Find senderOrigin (TARGET SIDE)
  607.                     // 5. Overwrite #4 with mappingObject
  608.  
  609.                     // Step 1
  610.                     var tempGetDbData;
  611.                     if (event.info.previousKeyValue == null) {
  612.                         tempGetDbData = event.info.key.value;
  613.                     }
  614.                     else {
  615.                         tempGetDbData = event.info.previousKeyValue;
  616.                     }
  617.  
  618.                     return getDbData(tempGetDbData)
  619.                         .then(function (sourceDbData) {
  620.                             if (!sourceDbData) { if (debug) { console.log('Error in getting dbData document'); } return Promise.resolve(false); }
  621.                             //Looping through keys to get field objects.
  622.                             if (event.info.previousKeyValue != null) {
  623.                                 var oldSourceField = getField(sourceDbData, event.info.previousKeyValue);
  624.                                 // Step 2
  625.  
  626.                                 for (var i = 0; i < oldSourceField.mappings.length; i++) {
  627.                                     var linkID = oldSourceField.mappings[i].link._id;
  628.                                     if (linkID == event.senderOrigin._id) {
  629.                                         oldSourceField.mappings.splice(i, 1);
  630.                                         // Just for safety, marking things as modified so the DB knows to change them
  631.                                         oldSourceField.markModified('mappings');
  632.                                         break;
  633.                                     }
  634.                                 }
  635.  
  636.                                 if (debug) {
  637.                                     console.log('Removed old mapping from source side');
  638.                                 }
  639.                             }
  640.                             // Step 3
  641.                             if (event.info.key.value != null) {
  642.                                 // If adding/updating/editing a level, need to add to the source side
  643.  
  644.  
  645.                                 var newSourceField = getField(sourceDbData, event.info.key.value);
  646.                                 newSourceField.mappings.push({
  647.                                     type: 'lookup',
  648.                                     link: event.senderOrigin,
  649.                                     separator: ''
  650.                                 });
  651.                                 // Mark as modified
  652.                                 newSourceField.markModified('mappings');
  653.                                 if (debug) { console.log('Added new lookup mapping to the new source field as follows:'); console.log(newSourceField.mappings[0].link); }
  654.                             }
  655.                             return sourceDbData.save();
  656.                         })
  657.                         .then(function (saveSourceResult) {
  658.                             if (!saveSourceResult) { if (debug) { console.log('Failed to Save Source Document'); } return Promise.resolve(false); }
  659.                             // Step 4
  660.                             return getDbData(event.senderOrigin);
  661.                         })
  662.                         .then(function (targetDbData) {
  663.                             if (!targetDbData) { if (debug) { console.log('Error in getting sender DbData'); } return Promise.resolve(false); }
  664.                             // Step 5
  665.                             var targetField = getField(targetDbData, event.senderOrigin);
  666.                             targetField.mappings[event.info.mappingIndex] = event.info.mappingObject;
  667.                             //Marking field as modified for the DB
  668.                             targetField.markModified('mappings.' + event.info.mappingIndex);
  669.                             if (debug) { console.log('Removed level object from target side.  New mapping array for target: '); console.log(targetField.mappings[event.info.mappingIndex]); }
  670.                             return targetDbData.save();
  671.                         })
  672.                         .then(function (saveTargetResult) {
  673.                             if (!saveTargetResult) { if (debug) { console.log('Failed to Save Target Document'); } return Promise.resolve(false); }
  674.                             // Save was successful
  675.                             return Promise.resolve(true);
  676.                         })
  677.                         .then(function (endResult) {
  678.                             if (debug) { console.log('Completed Edit Level logic.  Promise is returning true!'); }
  679.                             return Promise.resolve(true);
  680.                         })
  681.                         .catch(function (err) {
  682.                             if (debug) { console.log('Edit Level | Promise catch for uncaught errors.  Error: ' + err); }
  683.                             Promise.resolve(false);
  684.                         });
  685.                     break;
  686.                 default:
  687.                     if (debug) { console.log('Server received map event with unknown mapping action: ' + event.mappingAction); }
  688.                     break;
  689.             }
  690.             break;
  691.         case 'updateDBField':
  692.             // find and update a dbField here
  693.             return getDbData(event.senderOrigin)
  694.                 .then(function (dbData) {
  695.                     if (!dbData) { if (debug) { console.log('Error in getting dbData document'); } return Promise.resolve(false); }
  696.                     // Step 2
  697.                     var field = getField(dbData, event.senderOrigin);
  698.                     for (var prop in event.value) {
  699.                         if (event.value.hasOwnProperty(prop)) {
  700.                             console.log('Prop Value: ' + event.value[prop]);
  701.                             // field.set(prop, event.value[prop]);
  702.                             // console.log(field);
  703.                             field[prop] = event.value[prop];
  704.                             field.markModified(prop);
  705.                             // dbData.markModified(field);
  706.                         }
  707.                     }
  708.                     if (debug) { console.log('updated dbField ' + event.senderOrigin.name); }
  709.                     // Step 3
  710.                     return dbData.save();
  711.                 })
  712.                 .then(function (endResult) {
  713.                     if (debug) { console.log('Completed updateDbField logic.  Promise is returning true!'); }
  714.                     return Promise.resolve(true);
  715.                 })
  716.                 .catch(function (err) {
  717.                     if (debug) { console.log('updateDbField | Promise catch for uncaught errors.  Error: ' + err); }
  718.                     // Is this a good idea?  IDK what this will do...
  719.                     Promise.resolve(false);
  720.                 });
  721.             break;
  722.         case 'updateDBTable':
  723.             // find and update a dbField here
  724.             return getDbData(event.senderOrigin)
  725.                 .then(function (dbData) {
  726.                     if (!dbData) { if (debug) { console.log('Error in getting dbData document'); } return Promise.resolve(false); }
  727.                     // Step 2
  728.                     var table = getTable(dbData, event.senderOrigin);
  729.                     for (var prop in event.value) {
  730.                         if (event.value.hasOwnProperty(prop)) {
  731.                             table[prop] = event.value[prop];
  732.                             table.markModified(prop);
  733.                         }
  734.                     }
  735.                     if (debug) { console.log('updated dbTable ' + event.senderOrigin.name); }
  736.                     // Step 3
  737.                     return dbData.save();
  738.                 })
  739.                 .then(function (endResult) {
  740.                     if (debug) { console.log('Completed updateDbTable logic.  Promise is returning true!'); }
  741.                     return Promise.resolve(true);
  742.                 })
  743.                 .catch(function (err) {
  744.                     if (debug) { console.log('updateDbTable | Promise catch for uncaught errors.  Error: ' + err); }
  745.                     Promise.resolve(false);
  746.                 });
  747.             break;
  748.         case 'updateDBSchema':
  749.             // find and update a dbField here
  750.             return getDbData(event.senderOrigin)
  751.                 .then(function (dbData) {
  752.                     if (!dbData) { if (debug) { console.log('Error in getting dbData document'); } return Promise.resolve(false); }
  753.                     // Step 2
  754.                     var schema = getSchema(dbData, event.senderOrigin);
  755.                     for (var prop in event.value) {
  756.                         if (event.value.hasOwnProperty(prop)) {
  757.                             schema[prop] = event.value[prop];
  758.                             schema.markModified(prop);
  759.                         }
  760.                     }
  761.                     if (debug) { console.log('updated dbSchema ' + event.senderOrigin.name); }
  762.                     // Step 3
  763.                     return dbData.save();
  764.                 })
  765.                 .then(function (endResult) {
  766.                     if (debug) { console.log('Completed updateDbSchema logic.  Promise is returning true!'); }
  767.                     return Promise.resolve(true);
  768.                 })
  769.                 .catch(function (err) {
  770.                     if (debug) { console.log('updateDbSchema | Promise catch for uncaught errors.  Error: ' + err); }
  771.                     Promise.resolve(false);
  772.                 });
  773.             break;
  774.         case 'updateDBData':
  775.             // find and update a dbData here
  776.             return getDbData(event.senderOrigin)
  777.                 .then(function (dbData) {
  778.                     if (!dbData) { if (debug) { console.log('Error in getting dbData document'); } return Promise.resolve(false); }
  779.                     // Step 2
  780.                     var data = dbData;
  781.                     for (var prop in event.value) {
  782.                         if (event.value.hasOwnProperty(prop)) {
  783.                             data[prop] = event.value[prop];
  784.                             data.markModified(prop);
  785.                         }
  786.                     }
  787.                     if (debug) { console.log('updated dbData ' + event.senderOrigin.name); }
  788.                     // Step 3
  789.                     return dbData.save();
  790.                 })
  791.                 .then(function (endResult) {
  792.                     if (debug) { console.log('Completed updateDbData logic.  Promise is returning true!'); }
  793.                     return Promise.resolve(true);
  794.                 })
  795.                 .catch(function (err) {
  796.                     if (debug) { console.log('updateDbData | Promise catch for uncaught errors.  Error: ' + err); }
  797.                     Promise.resolve(false);
  798.                 });
  799.             break;
  800.         case 'add':
  801.             switch (event.componentName) {
  802.                 case 'DBField':
  803.                     // find and update a dbField here
  804.                     return getDbData(event.component)
  805.                         .then(function (dbData) {
  806.                             if (!dbData) {
  807.                                 if (debug) { console.log('Error in getting dbData document'); }
  808.                                 return Promise.resolve(false);
  809.                             }
  810.                             // Step 2
  811.                             var parentTable = getTable(dbData, event.component);
  812.                             parentTable.dbFields.push({
  813.                                 name: event.component.name,
  814.                                 mappings: event.component.mappings,
  815.                                 description: event.component.description,
  816.                                 notes: event.component.notes
  817.                             });
  818.                             if (debug) {
  819.                                 console.log('added new dbField ' + event.component.name);
  820.                             }
  821.                             // Step 3
  822.                             return dbData.save();
  823.                         })
  824.                         .then(function (endResult) {
  825.                             var parentTable = getTable(endResult, event.component);
  826.                             event.component._id = parentTable.dbFields[parentTable.dbFields.length - 1]._id;
  827.                             event.hasID = true;
  828.                             eventsToPush.push(event);
  829.                             if (debug) { console.log('Completed addDbField logic.  Promise is returning true!'); }
  830.                             return Promise.resolve(true);
  831.                         })
  832.                         .catch(function (err) {
  833.                             if (debug) { console.log('addDbField | Promise catch for uncaught errors.  Error: ' + err); }
  834.                             Promise.resolve(false);
  835.                         });
  836.                     break;
  837.                 case 'DBTable':
  838.                     // find and update a dbField here
  839.                     return getDbData(event.component)
  840.                         .then(function (dbData) {
  841.                             if (!dbData) {
  842.                                 if (debug) { console.log('Error in getting dbData document'); }
  843.                                 return Promise.resolve(false);
  844.                             }
  845.                             // Step 2
  846.                             console.log('Name: ' + event.component.name);
  847.                             var parentSchema = getSchema(dbData, event.component);
  848.                             parentSchema.dbTables.push({
  849.                                 name: event.component.name,
  850.                                 dbFields: event.component.dbFields,
  851.                                 description: event.component.description,
  852.                                 notes: event.component.notes,
  853.                                 done: false,
  854.                                 issue: false
  855.                             });
  856.                             if (debug) {
  857.                                 console.log('added new dbTable ' + event.component.name);
  858.                             }
  859.                             // Step 3
  860.                             return dbData.save();
  861.                         })
  862.                         .then(function (endResult) {
  863.                             var parentSchema = getSchema(endResult, event.component);
  864.                             event.component._id = parentSchema.dbTables[parentSchema.dbTables.length - 1]._id;
  865.                             event.hasID = true;
  866.                             eventsToPush.push(event);
  867.                             if (debug) { console.log('Completed addDbTable logic.  Promise is returning true!'); }
  868.                             return Promise.resolve(true);
  869.                         })
  870.                         .catch(function (err) {
  871.                             if (debug) { console.log('addDbTable | Promise catch for uncaught errors.  Error: ' + err); }
  872.                             Promise.resolve(false);
  873.                         });
  874.                     break;
  875.                 case 'DBSchema':
  876.                     // find and update a dbField here
  877.                     return getDbData(event.component)
  878.                         .then(function (dbData) {
  879.                             if (!dbData) {
  880.                                 if (debug) { console.log('Error in getting dbData document'); }
  881.                                 return Promise.resolve(false);
  882.                             }
  883.                             // Step 2
  884.                             var parentData = dbData;
  885.                             parentData.dbSchemas.push({
  886.                                 name: event.component.name,
  887.                                 dbTables: [],
  888.                                 notes: event.component.notes,
  889.                                 description: event.component.description
  890.                             });
  891.                             if (debug) {
  892.                                 console.log('added new dbSchema ' + event.component.name);
  893.                             }
  894.                             // Step 3
  895.                             return dbData.save();
  896.                         })
  897.                         .then(function (endResult) {
  898.                             var parentData = endResult;
  899.                             event.component._id = parentData.dbSchemas[parentData.dbSchemas.length - 1]._id;
  900.                             event.hasID = true;
  901.                             eventsToPush.push(event);
  902.                             if (debug) { console.log('Completed addDbSchema logic.  Promise is returning true!'); }
  903.                             return Promise.resolve(true);
  904.                         })
  905.                         .catch(function (err) {
  906.                             if (debug) { console.log('addDbSchema | Promise catch for uncaught errors.  Error: ' + err); }
  907.                             Promise.resolve(false);
  908.                         });
  909.                     break;
  910.                 default:
  911.                     if (debug) { console.log('Server received add event with unknown component name: ' + event.componentName); }
  912.                     break;
  913.             }
  914.             break;
  915.         case 'remove':
  916.             switch (event.componentName) {
  917.                 case 'DBField':
  918.                     // find and remove a dbField here
  919.                     return getDbData(event.component)
  920.                         .then(function (dbData) {
  921.                             if (!dbData) {
  922.                                 if (debug) { console.log('Error in getting dbData document'); }
  923.                                 return Promise.resolve(false);
  924.                             }
  925.                             // Step 2
  926.                             getTable(dbData, event.component).dbFields.remove({ _id: event.component._id });
  927.                             if (debug) {
  928.                                 console.log('removed dbField ' + event.component.name);
  929.                             }
  930.                             // Step 3
  931.                             return dbData.save();
  932.                         })
  933.                         .then(function (endResult) {
  934.                             if (debug) { console.log('Completed removeDbField logic.  Promise is returning true!'); }
  935.                             return Promise.resolve(true);
  936.                         })
  937.                         .catch(function (err) {
  938.                             if (debug) { console.log('removeDbField | Promise catch for uncaught errors.  Error: ' + err); }
  939.                             Promise.resolve(false);
  940.                         });
  941.                     break;
  942.                 case 'DBTable':
  943.                     // find and remove a dbTablehere
  944.                     return getDbData(event.component)
  945.                         .then(function (dbData) {
  946.                             if (!dbData) {
  947.                                 if (debug) { console.log('Error in getting dbData document'); }
  948.                                 return Promise.resolve(false);
  949.                             }
  950.                             // Step 2
  951.                             getSchema(dbData, event.component).dbTables.remove({ _id: event.component._id });
  952.                             if (debug) {
  953.                                 console.log('removed dbTable ' + event.component.name);
  954.                             }
  955.                             // Step 3
  956.                             return dbData.save();
  957.                         })
  958.                         .then(function (endResult) {
  959.                             if (debug) { console.log('Completed removeDbTable logic.  Promise is returning true!'); }
  960.                             return Promise.resolve(true);
  961.                         })
  962.                         .catch(function (err) {
  963.                             if (debug) { console.log('removeDbTable | Promise catch for uncaught errors.  Error: ' + err); }
  964.                             Promise.resolve(false);
  965.                         });
  966.                     break;
  967.                 case 'DBSchema':
  968.                     // find and remove a dbSchema here
  969.                     return getDbData(event.component)
  970.                         .then(function (dbData) {
  971.                             if (!dbData) {
  972.                                 if (debug) { console.log('Error in getting dbData document'); }
  973.                                 return Promise.resolve(false);
  974.                             }
  975.                             // Step 2
  976.                             dbData.dbSchemas.remove({ _id: event.component._id });
  977.                             if (debug) {
  978.                                 console.log('removed dbSchema' + event.component.name);
  979.                             }
  980.                             // Step 3
  981.                             return dbData.save();
  982.                         })
  983.                         .then(function (endResult) {
  984.                             if (debug) { console.log('Completed removeDbSchema logic.  Promise is returning true!'); }
  985.                             return Promise.resolve(true);
  986.                         })
  987.                         .catch(function (err) {
  988.                             if (debug) { console.log('removeDbSchema | Promise catch for uncaught errors.  Error: ' + err); }
  989.                             Promise.resolve(false);
  990.                         });
  991.                     break;
  992.                 default:
  993.                     if (debug) { console.log('Server received remove event with unknown component name: ' + event.componentName); }
  994.                     break;
  995.             }
  996.             break;
  997.         default:
  998.             if (debug) { console.log('Server received event with unknown action: ' + event.action); }
  999.             break;
  1000.     }
  1001.     //If reach this point, something broke out of switch statement, so this event was skipped
  1002.     // Promise resolution doesn't really matter here, the value is never used in the processQueue() function
  1003.     return Promise.resolve(false);
  1004.  
  1005. }
  1006.  
  1007. function checkEvents(socket, io) {
  1008.     if (eventsToPush.length > 0) {
  1009.         for (var i = 0; i < eventsToPush.length; i++) {
  1010.             // console.log(eventsToPush[i]);
  1011.             // socket.emit('state-has-changed');
  1012.             io.emit('state-has-changed', eventsToPush[i]);
  1013.             eventsToPush.splice(i, 1);
  1014.             if (debug) { console.log('Pushed an event back to all clients from server'); }
  1015.         }
  1016.     }
  1017. }
  1018.  
  1019. function processQueue(socket, io, isRecursion) {
  1020.     if (typeof isRecursion == "undefined") {
  1021.         isRecursion = false;
  1022.     }
  1023.     if (isRecursion || !isProcessingQueue) {
  1024.         //Start processing queue
  1025.         isProcessingQueue = true;
  1026.         if (debug) { console.log('Queue processing has officially begun!'); }
  1027.  
  1028.         //First, need copy of queue so it doesn't changeeeeeee
  1029.         var localQueue = masterEventQueue.slice();
  1030.  
  1031.         //Safety measure to prevent server overload...
  1032.         recursionSafetyCount += 1;
  1033.  
  1034.  
  1035.  
  1036.         var runEventPromise = localQueue.reduce(function (promise, item) {
  1037.             return promise.then(function (result) {
  1038.                 if (result === false) {
  1039.                     //Event was skipped, there was some error
  1040.                     console.log('[ERROR] Server skipping event, no action taken.');
  1041.                     if (!debug) { console.log('To find out where the error occurred, please turn on DEBUG mode and retry'); }
  1042.                 }
  1043.                 checkEvents(socket, io);
  1044.                 return executeEvent(item);
  1045.             })
  1046.         }, Promise.resolve());
  1047.  
  1048.         return runEventPromise.then(function (result) {
  1049.             if (result === false) {
  1050.                 //Event was skipped, there was some error
  1051.                 console.log('[ERROR] Server skipping event, no action taken.');
  1052.                 if (!debug) { console.log('To find out where the error occurred, please turn on DEBUG mode and retry'); }
  1053.             }
  1054.             checkEvents(socket, io);
  1055.             //Clear queue of processed things
  1056.             masterEventQueue.splice(0, localQueue.length);
  1057.             if (debug) { console.log('Post-Run Queue Length: ' + masterEventQueue.length); console.log('Queue process cycle completed'); }
  1058.  
  1059.             //Check if anything was added to process in the queue??
  1060.             if (masterEventQueue.length > 0) {
  1061.                 //Recur as long as there's still events to process!
  1062.                 //First, be safe with recursion!
  1063.                 if (recursionSafetyCount < 100) {
  1064.                     return processQueue(socket, io, true);
  1065.                 }
  1066.                 else {
  1067.                     console.log('Queue processing recurred 100 times!  Something might be wrong with the system...');
  1068.                     console.log('Time to take a break!');
  1069.                     setTimeout(function () {
  1070.                         console.log('Paused execution for 30 seconds');
  1071.                         //Immediately release lock on queue
  1072.                         isProcessingQueue = false;
  1073.                         // Reset Recursion Count
  1074.                         recursionSafetyCount = 0;
  1075.                         return Promise.reject('Recursion Counter Reached!');
  1076.                     }, 30000);
  1077.                 }
  1078.             }
  1079.             else {
  1080.                 //Immediately release lock on queue
  1081.                 isProcessingQueue = false;
  1082.                 // Reset Recursion Count
  1083.                 recursionSafetyCount = 0;
  1084.                 return Promise.resolve('Finished Processing Event');
  1085.             }
  1086.         }).catch(function (err) {
  1087.             console.log('Error: ' + event.action + ' - dbOperation catch - ' + err);
  1088.         });
  1089.     }
  1090.     else {
  1091.         return Promise.resolve(false);
  1092.     }
  1093. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement