SYNCING bugs fixed -- MesageQueue+SynchronousChecks

This commit is contained in:
Curtis SerVaas
2014-08-21 09:37:46 -07:00
parent ecbdca040d
commit 63af9b9b21
9 changed files with 295 additions and 195 deletions
+3
View File
@@ -8,7 +8,10 @@ var passport = require('passport');
var flash = require('connect-flash');
require('./config/passport')(passport); // pass passport for configuration
require("./models/Node.js");
//This isn't used in this file, but calling it before helper lib avoids circularDependencies.
var helperLib = require('./lib/helperLib.js');
console.log(helperLib);
helperLib.safeConnectToDB();
+90
View File
@@ -0,0 +1,90 @@
var Node = require("../models/Node.js");
var MessageQueue = [];
module.exports.iterateQueue = function(){
// console.log("iteratingQueue");
MessageQueue.shift(); //remove the finished operation.
if(MessageQueue.length == 0){return;}
var nextOperation = MessageQueue[0];
executeOperation(nextOperation);
}
//queueLength needs to be != 0 if there's an operation occuring.
module.exports.queueOrDo = function(operation){
if(MessageQueue.length == 0){
MessageQueue.push(operation);
executeOperation(operation);
}
else{
// console.log("QUEUE BEING USED!!!");
MessageQueue.push(operation);
}
}
function executeOperation(operation){
var type = operation[0];
var data = operation[1];
var socket = operation[2];
switch(type){
case "newNode":
addNode(data, socket); break;
case "removeNode":
removeNode(data, socket); break;
case "movedNode":
moveNode(data, socket); break;
default:
break;
}
}
function moveNode(data, socket){
// var ids = [thisModel.get("_id"), oldParModel.get("_id"), newParModel.get("_id")];
// var arrays = [thisModel.get("parents"), oldParModel.get("children"), newParModel.get("children")];
// var indices = [dragIndex, dropIndex];
// var data = [ids, arrays, indices, CurrentUser];
Node.moveNode(data[0], data[1],data[3]._id);
}
function removeNode(data, socket){
var thisId = data[0];
var thisIndex = data[1];
var parId = data[2];
var author = data[3];
// data[3] = null; //improve efficiency.
Node.removeNode(thisId, thisIndex, parId, author._id);
}
//need to broadcast parentArray.
function addNode(data, socket){
var modelJson = data[1]; //(includes the negative ID to find later);
var parId = data[0][0];
var newIndex = data[0][1];
var Author = data[2];
var now = Date.now();
var callback = function(err, instance, now){
socket.emit("updateReceived", [modelJson._id ,instance, data[0]]);
socket.broadcast.emit("newNode", [ [parId,newIndex] , instance ]);
Node.updateParent(parId, instance._id ,newIndex, now );
}
// console.log("newNode");
Node.addNode(modelJson.text, modelJson.children, modelJson.parents, modelJson.author._id ,callback);
}
+13 -42
View File
@@ -14,8 +14,14 @@ var lastExchangeData = {};
var makeCommit = require("./makeCommit.js").makeCommit;
var getAndSendRevHistory = require("./revAlgorithm.js").getAndSendRevHistory;
var MessageQueue =require("./MessageQueue.js");
console.log("MessageQueue");
console.log(MessageQueue);
module.exports = {
iterateQueue: MessageQueue.iterateQueue,
safeConnectToDB: function(){
var url = require("../config/config.js").DB_URL;
try { mongoose.connect(url); }
@@ -109,56 +115,21 @@ function attachLogInListeners(socket){
// });
socket.on("newNode", function(data){
var modelJson = data[1]; //(includes the negative ID to find later);
var parId = data[0][0];
var newIndex = data[0][1];
var Author = data[2];
var now = Date.now();
var callback = function(err, instance, now){
socket.emit("updateReceived", [modelJson._id ,instance, data[0]]);
socket.broadcast.emit("newNode", [ [parId,newIndex] , instance ]);
Node.updateParent(parId, instance._id ,newIndex, now );
}
console.log("newNode");
Node.addNode(modelJson.text, modelJson.children, modelJson.parents, modelJson.author._id ,callback);
});
//maybe emit sooner...
//need to broadcast parentArray.
socket.on("newNode", function(data){
MessageQueue.queueOrDo(['newNode', data, socket])
});
socket.on("removeNode", function(data){
var thisId = data[0];
var thisIndex = data[1];
var parId = data[2];
var author = data[3];
// data[3] = null; //improve efficiency.
socket.broadcast.emit("removeNode", data);
Node.removeNode(thisId, thisIndex, parId, author._id);
MessageQueue.queueOrDo(['removeNode', data, socket])
});
socket.on("movedNode", function(data){
// var ids = [thisModel.get("_id"), oldParModel.get("_id"), newParModel.get("_id")];
// var arrays = [thisModel.get("parents"), oldParModel.get("children"), newParModel.get("children")];
// var indices = [dragIndex, dropIndex];
// var data = [ids, arrays, indices, CurrentUser];
Node.moveNode(data[0], data[1],data[3]._id);
socket.broadcast.emit("movedNode", [data[0], data[2]]);
MessageQueue.queueOrDo(['movedNode', data, socket])
});
socket.on("getTimeHash", function(){
var timeHash = getTimeHash();
socket.emit("timeHash", timeHash);
}) ;
}
+91 -67
View File
@@ -72,73 +72,6 @@ function setUpDB(){
});
}
function moveNode(ids, arrays, authorId){
var now = Date.now();
var thisId = ids[0]; //draggedId
MyNode.findById(thisId, null, function(err, node){
node.author = authorId; //
node.timestamp = now;
node.parents = arrays[0];
node.save();
});
var oldParId = ids[1];
MyNode.findById(oldParId, null, function(err, node){
node.timestamp = now;
node.children = arrays[1];
node.save();
});
var newParId = ids[2];
MyNode.findById(newParId, null, function(err, node){
node.timestamp = now;
node.children = arrays[2];
node.save();
});
}
function removeNode(thisId, thisIndex, parId, authorId){
var now = Date.now();
MyNode.findById(parId, null, function(err, parNode){
if(err || parNode == null){
return;
}
var temp = parNode.children;
temp.splice(thisIndex, 1); //remove thisIndex.
parNode.children = temp;
parNode.timestamp = now;
parNode.save();
});
MyNode.findById(thisId, null, function(err, delNode){
if(err || delNode == null){
return;
}
delNode.author = authorId;
delNode.timestamp = now;
if(delNode.parents.length ==1 ){//(this if statement is technically redundant)
// delNode.remove();
delNode.parents = []; //(this is how deletion is represented).
delNode.save();
}
else{ //this is the condition that we'll have to take care of if there are dups.
delNode.parents = _.without(delNode.parents, parId);
delNode.save();
}
})
}
function updateText(id, newText, authorId){
MyNode.findById(id, null, function(err, node){
if(err || node == null){
@@ -156,6 +89,90 @@ function updateText(id, newText, authorId){
function moveNode(ids, arrays, authorId){
var now = Date.now();
var numCallbacks = 0;
var thisId = ids[0]; //draggedId
MyNode.findById(thisId, null, function(err, node){
node.author = authorId; //
node.timestamp = now;
node.parents = arrays[0];
node.save(parallelExecutionHelper);
});
var oldParId = ids[1];
MyNode.findById(oldParId, null, function(err, node){
node.timestamp = now;
node.children = arrays[1];
node.save(parallelExecutionHelper);
});
var newParId = ids[2];
MyNode.findById(newParId, null, function(err, node){
node.timestamp = now;
node.children = arrays[2];
node.save(parallelExecutionHelper);
});
function parallelExecutionHelper(){
numCallbacks++;
if(numCallbacks==3){
console.log("FINISHED- MoveNode,ParallelExecutionHelper")
helperLib.iterateQueue();
numCallbacks=0;
}
}
}
function removeNode(thisId, thisIndex, parId, authorId){
var now = Date.now();
MyNode.findById(parId, null, function(err, parNode){
if(err || parNode == null){
return;
}
var temp = parNode.children;
temp.splice(thisIndex, 1); //remove thisIndex.
parNode.children = temp;
parNode.timestamp = now;
parNode.save(function(){helperLib.iterateQueue()});
});
MyNode.findById(thisId, null, function(err, delNode){
if(err || delNode == null){
return;
}
delNode.author = authorId;
delNode.timestamp = now;
if(delNode.parents.length ==1 ){//(this if statement is technically redundant)
// delNode.remove();
delNode.parents = []; //(this is how deletion is represented).
delNode.save();
}
else{ //this is the condition that we'll have to take care of if there are dups.
delNode.parents = _.without(delNode.parents, parId);
delNode.save();
}
});
}
function updateParent(parId, newId ,newIndex,now){
MyNode.findById(parId, null, function(err, parNode){
if(err || parNode == null){
@@ -166,6 +183,7 @@ function updateParent(parId, newId ,newIndex,now){
parNode.save();
})
}
//add Node to the DB.
function addNode(text, children, parents, authorId, callback){
var instance = new MyNode();
@@ -181,6 +199,7 @@ function addNode(text, children, parents, authorId, callback){
callback(err);
}
else {
helperLib.iterateQueue();
callback(null, instance);
}
});
@@ -206,3 +225,8 @@ Array.prototype.remove = function(from, to) {
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
var helperLib = require("../lib/helperLib.js");
console.log("HELPERLIB");
console.log(helperLib);
+41 -13
View File
@@ -1,5 +1,6 @@
$(function(){
//alert("jquery works");
INPUT_PROCESSED = true;
$("#COMMIT").click(function(){
@@ -73,15 +74,15 @@ $(function(){
var that = this;
voInitializer(that, event);
var id = $(event.target).closest("li").attr("data-id");
keydownHandler(event);
socket.emit("editing", [id, CurrentUser._id]);
socket.emit("editing", [id, CurrentUser.google.name]);
});
$("body").on("blur", "textarea", function(event){
var thisLI = $(event.target).closest("li");
var id = thisLI.attr("data-id");
var text = thisLI.children().children("textarea").val();
$("textarea").textareaAutoExpand();
socket.emit("blurred", [id, text, CurrentUser]);
});
@@ -143,6 +144,18 @@ function hasDuplicates(array) {
return false;
}
Array.prototype.removeOne = function(parId){
var parIndex = this.indexOf(parId);
this.remove(parIndex);
}
voInitializer = function(that, event){
//var that = this;
vo = {};
@@ -200,13 +213,33 @@ voInitializer = function(that, event){
}
keydownHandler = function(event){ //the entire body is wrapped in this.
var that = this;
console.log("keyDownHandler");
//
if(event.which == undefined){ return; }
if(event.which == undefined){ console.log("ABORTED- event.which==undefined"); return; }
if(!CurrentUser){ alert("only logged in users can edit"); return;}//prevent non-logged in users from editing.
if(!INPUT_PROCESSED){console.log("ABORT- INPUT_PROCESSED=false"); return;}//hitting-enter too quickly causes bugs. Need to make sure nodes have been added.
if(event.which == 13){event.preventDefault();}
voInitializer(that, event);
console.log("ABOUT TO PROCESS INPUT");
INPUT_PROCESSED = false;
//event.preventDefault();
//http://stackoverflow.com/questions/20964729/run-keydown-event-handler-after-the-value-of-a-textarea-has-been-changed
@@ -218,6 +251,8 @@ keydownHandler = function(event){ //the entire body is wrapped in this.
_.each(vo.thisModel.get("views"), function(view){
view.updateText()
});
INPUT_PROCESSED = true;
return;
}
if(vo.hitEnter){
@@ -266,7 +301,7 @@ keydownHandler = function(event){ //the entire body is wrapped in this.
if(vo.hitBack && vo.empty){
event.preventDefault();
removeNode(vo);
return;
}//hitBack.
// // START ON HIT TAB
@@ -332,14 +367,7 @@ if((vo.hitTab && event.shiftKey) || (event.keyCode == 37 && event.shiftKey)){//
}
Array.prototype.removeOne = function(parId){
var parIndex = this.indexOf(parId);
this.remove(parIndex);
}
}//keyboardHandler
+48 -69
View File
@@ -1,60 +1,18 @@
// voInitializer = function(that, event){
// vo = {};
// vo.hitEnter = (event.which == 13);
// vo.hitTab = (event.which ==9);
// vo.atEnd = ( $(that).getSelection().end == $(that).val().length);
// vo.atBeg = ( $(that).getSelection().start == 0);
// //cursor = $(this).getSelection().start;
// vo.hitBack = (event.which ==8);
// vo.empty = ($(that).val().length ==0);
// vo.rootLevel = $(that).closest("ul").is(".root")
// vo.lastBullet = ( $(that).closest("li").is(":first-child") && vo.rootLevel);
// vo.thisLI = $(event.target).closest("li");
// vo.thisId = vo.thisLI.attr("data-id"); //data-id.
// vo.thisIndex = vo.thisLI.index(); //returns -1 if there's no match.
// vo.thisModel = nodesCollection.findWhere({_id: vo.thisId});
// vo.siblingLI = vo.thisLI.prev();
// vo.siblingIndex = vo.siblingLI.index();
// vo.siblingId = vo.siblingLI.attr("data-id");
// vo.siblingModel = nodesCollection.findWhere({_id: vo.siblingId});
// console.log(nodesCollection);
// console.log(vo.thisModel);
// if(vo.rootLevel){
// vo.parentLI = undefined;
// vo.parentId = (vo.thisLI.closest("ul").attr("data-id"))
// vo.grandParentId = undefined; // won't matter since outTab prevents it. //unless programattic.
// }
// else{ //not root level.
// vo.parentLI = vo.thisLI.parent().closest("li");
// vo.parentId = (vo.parentLI.attr("data-id"));
// if(vo.parentLI.attr("data-depth") == 0){ //could test this another way.
// vo.grandParentId = vo.parentLI.closest("ul").attr("data-id");
// }
// else{
// vo.grandParentId = (vo.parentLI.parent().closest("li").attr('data-id'));
// }
// }
// vo.grandParentModel = nodesCollection.findWhere({_id: vo.grandParentId});
// vo.parentModel = nodesCollection.findWhere({_id: vo.parentId});
// }
// keydownHandler = function(event){ //the entire body is wrapped in this.
// var that = this;
// console.log("keyDownHandler");
// //
// if(event.which == undefined){ return; }
// if(event.which == undefined){ console.log("ABORTED- event.which==undefined"); return; }
// if(!CurrentUser){ alert("only logged in users can edit"); return;}//prevent non-logged in users from editing.
// if(!INPUT_PROCESSED){console.log("ABORT- INPUT_PROCESSED=false"); return;}//hitting-enter too quickly causes bugs. Need to make sure nodes have been added.
// if(event.which == 13){event.preventDefault();}
// voInitializer(that, event);
// console.log("ABOUT TO PROCESS INPUT");
// INPUT_PROCESSED = false;
// //minor-bug
// //event.preventDefault();
// //http://stackoverflow.com/questions/20964729/run-keydown-event-handler-after-the-value-of-a-textarea-has-been-changed
// //keyupp fixes this, but causes other problems.
@@ -65,6 +23,9 @@
// _.each(vo.thisModel.get("views"), function(view){
// view.updateText()
// });
// socket.emit("blurred", [id, text, CurrentUser]);
// INPUT_PROCESSED = true;
// return;
// }
// if(vo.hitEnter){
@@ -80,6 +41,7 @@
// if(!event.shiftKey){
// event.preventDefault();
// if(vo.empty){
// addNode("");
// return;
@@ -112,15 +74,42 @@
// if(vo.hitBack && vo.empty){
// event.preventDefault();
// removeNode(vo);
// return;
// }//hitBack.
// // // START ON HIT TAB
// // if (vo.hitTab) {
// // event.preventDefault();
// // if (event.shiftKey) {
// // event.preventDefault();
// // if (($(this).parent().parent().parent().hasClass("root"))) {
// // // do nothing. //alert() //IT USED TO BE ID = 'ROOT' // we use 'root SubList' because it has two classes.
// // }
// // else { // OUTDENT!!
// // var newIndex = $(this).parent().parent().parent().closest("li").index();
// // debugger;
// // moveNode(vo.thisModel, vo.thisIndex, vo.parentModel, vo.grandParentModel, newIndex+1, true);
// // }
// // }
// // var hasAboveSibling = (vo.thisIndex != 0);
// // if(!event.shiftKey && (hasAboveSibling) ){
// // var newIndex = vo.siblingModel.get("children").length; // no need for a + 1, because 0 index + insert (duh)
// // moveNode(vo.thisModel, vo.thisIndex, vo.parentModel, vo.siblingModel, newIndex, true);
// // }
// // }// END ON HIT TAB
// if((vo.hitTab && !event.shiftKey) || (event.keyCode == 39 && event.shiftKey)){ //INDENT
// event.preventDefault();
// var hasAboveSibling = (vo.thisIndex != 0);
// if(hasAboveSibling){
// var newIndex = vo.siblingModel.get("children").length; // no need for a + 1, because 0 index + insert (duh)
// moveNode(vo.thisModel, vo.thisIndex, vo.parentModel, vo.siblingModel, newIndex, true);
// setTimeout(function(){
// }, 100);
// }
// }
// if((vo.hitTab && event.shiftKey) || (event.keyCode == 37 && event.shiftKey)){// OUTDENT!!
@@ -128,14 +117,17 @@
// // do nothing. //alert() //IT USED TO BE ID = 'ROOT' // we use 'root SubList' because it has two classes.
// }
// else {
// var newSiblingUL = $(this).parent().parent().parent();
// var newIndex = newSiblingUL.closest("li").index();
// moveNode(vo.thisModel, vo.thisIndex, vo.parentModel, vo.grandParentModel, newIndex+1, true);
// setTimeout(function(){ //(MoveNode is asynchronous, so you need to wait a little bit.).
// newSiblingUL.parent().next().children().children("textarea").focus();
// }, 100);
// }//if->else
// }//if
// }
// }
// if(event.keyCode == 38 && event.shiftKey && !vo.thisLI.is(":first-child")) {
// moveNode(vo.thisModel, vo.thisIndex, vo.parentModel, vo.parentModel, vo.thisIndex-1, true);
@@ -146,19 +138,6 @@
// return;
// }
// }//vo-initializer
// Array.prototype.removeOne = function(parId){
// var parIndex = this.indexOf(parId);
// this.remove(parIndex);
// }
// }
+6 -4
View File
@@ -1,6 +1,4 @@
addNode = function(botStr, topStr){
// debugger;
var randomId = ( -1 * Math.floor( Math.random() * 100000000) )
var modelJSON = {
_id: randomId
@@ -27,7 +25,9 @@ addNode = function(botStr, topStr){
vo.parentModel.get("children").insert(vo.thisIndex + 1, randomId);
socket.emit("newNode", [ [vo.parentId, vo.thisIndex+1] , modelJSON ]);
var data = [ [vo.parentId, vo.thisIndex+1] , modelJSON ];
console.log("AddNode DATA"); console.log(data);
socket.emit("newNode", data);
var parentViews = vo.parentModel.get("views");
@@ -36,6 +36,8 @@ addNode = function(botStr, topStr){
parentView.addNode(newNode, tempIndex, true);
});
vo.thisLI.next().children().children("textarea").focus();
INPUT_PROCESSED=true;
console.log("FINISHED- ADD NODE")
}
//topStr is to the left. (also, the bottom part will be to the right. )
@@ -79,7 +81,7 @@ transclude = function(){
});
vo.thisLI.next().children().children("textarea").focus();
INPUT_PROCESSED=true;
}
+1
View File
@@ -32,4 +32,5 @@ var moveNode = function(thisModel, dragIndex, oldParModel, newParModel, dropInde
socket.emit("movedNode", data);
}
INPUT_PROCESSED=true;
}
+2
View File
@@ -41,4 +41,6 @@ var upDateParentModelViews = function(vo, broadcast){
_.each(vo.parentModel.get("views"), function(parentView){
parentView.removeNode(vo.thisIndex);
});
INPUT_PROCESSED=true;
}