Last active
August 29, 2015 14:19
-
-
Save formula1/b56d74bc448ff6fd353d to your computer and use it in GitHub Desktop.
One to Many, Recursive
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Cone | |
*/ | |
var SortedBacklog = require("./SortedBacklog"); | |
function Cone(originator,child_limit,stay_alive){ | |
this.stay_alive = (typeof stayalive === "undefined")?true:stay_alive; | |
this.child_limit = child_limit||7; | |
this.originator = originator; | |
this.backlog = new SortedBacklog(); | |
} | |
Cone.prototype.enter = function(item){ | |
var parent = this.backlog.getAtIndex(0); | |
if(parent.children.length === this.child_limit -1){ | |
this.backlog.remove(parent); | |
} | |
item.parent = parent; | |
item.children = []; | |
parent.children.push(item); | |
this.backlog.push(item); | |
this.emit("enter",item); | |
}; | |
Cone.prototype.exit = function(item,next){ | |
if(item.children.length > 0){ | |
this.replace(item); | |
}else{ | |
this.parentCanGetMore(item); | |
} | |
}; | |
Cone.prototype.replace = function(oldItem){ | |
//Need an easy to use method of finding the last item and removing it | |
var newestItem = this.backlog.getAtIndex(-1); | |
this.backlog.remove(newestItem); | |
newestItem.children = oldItem.children; | |
newestItem.parent = oldItem.parent; | |
//need an easy to use method of replacing the backlog | |
this.backlog.set(oldItem,newestItem); | |
this.emit("replace",oldItem,newestItem); | |
}; | |
Cone.prototype.parentCanGetMore = function(item){ | |
var parent = item.parent; | |
parent.children.splice(parent.children.indexOf(item),1); | |
this.backlog.remove(item); | |
this.backlog.insert(parent); | |
this.emit("exit",item); | |
}; | |
Cone.prototype.stdListeners = function(){ | |
var self = this; | |
this.on("replace",function(oldItem,newItem){ | |
self.removeAllRelatonships(newItem, function(err){ | |
if(err) throw err; | |
async.each(newItem.children,function(child,next){ | |
self.addRelationship(newItem,child,next); | |
},function(err){ | |
if(err) throw err; | |
}); | |
}); | |
}); | |
this.on("exit",function(item){ | |
//its likely that if the user disconnected from us, | |
//they likely disconnected from The other party. | |
//just in case though, we most likely want to remove the relationship | |
//Since it may cause the parent to have more children than they should | |
self.removeRelationship(item.parent,item); | |
}); | |
this.on("enter",function(item){ | |
self.addRelationship(item.parent,item,function(err){ | |
if(err) throw err; | |
item.get("watcher_limit",function(err,limit){ | |
if(err) throw err; | |
item.limit = limit; | |
}); | |
}); | |
}); | |
}; | |
Cone.prototype.removeAllRelationships = function(item,next){ | |
throw new Error("removeRelationships is an abstract that should be overridden"); | |
item.send("remove_parent"); | |
var t, l; | |
l = function(){ | |
clearTimeout(t); | |
next(); | |
}; | |
t = setTimeout(function(){ | |
item.removeListener("parent_removed",l); | |
next(new Error("timed out")); | |
},10*1000); | |
item.on("parent_removed",l); | |
}; | |
Cone.prototype.removeRelationship = function(parent,child,next){ | |
throw new Error("removeRelationships is an abstract that should be overridden"); | |
parent.send("remove_child",child._id); | |
var t, l; | |
l = function(id){ | |
if(id !== child._id) return; | |
clearTimeout(t); | |
next(); | |
}; | |
t = setTimeout(function(){ | |
item.removeListener("child_removed",l); | |
next(new Error("timed out")); | |
},10*1000); | |
item.on("parent_removed",l); | |
}; | |
Cone.prototype.addRelationship = function(parent,child,next){ | |
throw new Error("addRelationship is an abstract that should be overridden"); | |
return child.getOffer() | |
.then(function(offer){ | |
return parent.getAccept(offer); | |
}).then(function(accept){ | |
return child.finalize(accept); | |
}); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function SortedBacklog(){ | |
this.obj = {}; | |
var isDirty = false; | |
var cachedKeys = []; | |
this.resetKeys = function(){ | |
isDirty = true; | |
}; | |
Object.defineProperty(this,keys,{ | |
get:function(){ | |
if(isDirty){ | |
cachedKeys = Object.keys(this.obj); | |
cachedKeys.sort(function(a,b){ | |
return parseInt(a.time) - parseInt(b.time); | |
}); | |
} | |
return cachedKeys; | |
},set:function(y){ | |
var first = cachedKeys[0]; | |
if(y < first){ | |
cachedKeys.unshift(y); | |
return; | |
} | |
var last = cachedKeys[cachedKeys.length-1]; | |
if(y > last){ | |
cachedKeys.push(y); | |
return; | |
} | |
self.resetKeys(); | |
} | |
}); | |
} | |
SortedBacklog.prototype.getAtIndex = function(index){ | |
if(index == -1){ | |
index = this.keys.length -1; | |
} | |
return this.obj[keys[index]]; | |
}; | |
SortedBacklog.prototype.push = function(item){ | |
item.time = Date.now(); | |
this.obj[item.time] = item; | |
this.keys = item.time; | |
}; | |
SortedBacklog.prototype.insert = function(item){ | |
if(!("time" in item)) throw new Error("cannot insert an item without a time"); | |
if(item.time in this.obj){ | |
if(this.obj[item.time] != item) throw new Error("inserting a duplicant key"); | |
return console.warn("inserting the same item twice"); | |
} | |
this.obj[item.time] = item; | |
this.keys = item.time; | |
}; | |
SortedBacklog.prototype.set = function(oldItem,newItem){ | |
newItem.time = oldItem.time; | |
this.obj[oldItem.time] = newItem; | |
}; | |
SortedBacklog.prototype.remove = function(item){ | |
delete this.obj[keys[0]]; | |
this.resetKeys(); | |
return ret; | |
}; | |
module.exports = SortedBacklog; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment