mirror of
https://github.com/amark/gun.git
synced 2025-10-14 00:59:35 +00:00
basics
This commit is contained in:
parent
921000adc2
commit
356a971ddc
28
axe.js
28
axe.js
@ -25,20 +25,17 @@
|
|||||||
|
|
||||||
;USE(function(module){
|
;USE(function(module){
|
||||||
|
|
||||||
var AXE = USE('./root'), Gun = (AXE.window||{}).Gun || USE('./gun', 1);
|
var AXE = USE('./root'), Gun = (AXE.window||'').Gun || USE('./gun', 1);
|
||||||
(Gun.AXE = AXE).GUN = AXE.Gun = Gun;
|
(Gun.AXE = AXE).GUN = AXE.Gun = Gun;
|
||||||
var ST = 0;
|
var ST = 0;
|
||||||
|
|
||||||
Gun.on('opt', function(at){
|
Gun.on('opt', function(at){ start(at) ; this.to.next(at) }); // make sure to call the "next" middleware adapter.
|
||||||
start(at);
|
|
||||||
this.to.next(at); // make sure to call the "next" middleware adapter.
|
|
||||||
});
|
|
||||||
|
|
||||||
function start(at){
|
function start(at){
|
||||||
if(at.axe){ return }
|
if(at.axe){ return }
|
||||||
var opt = at.opt, peers = opt.peers;
|
var opt = at.opt, peers = opt.peers;
|
||||||
if(false === opt.axe){ return }
|
if(false === opt.axe){ return }
|
||||||
if((typeof process !== "undefined") && 'false' === ''+(process.env||{}).AXE){ return }
|
if((typeof process !== "undefined") && 'false' === ''+(process.env||'').AXE){ return }
|
||||||
var axe = at.axe = {}, tmp;
|
var axe = at.axe = {}, tmp;
|
||||||
// 1. If any remembered peers or from last cache or extension
|
// 1. If any remembered peers or from last cache or extension
|
||||||
// 2. Fallback to use hard coded peers from dApp
|
// 2. Fallback to use hard coded peers from dApp
|
||||||
@ -73,14 +70,14 @@
|
|||||||
var mesh = opt.mesh = opt.mesh || Gun.Mesh(at);
|
var mesh = opt.mesh = opt.mesh || Gun.Mesh(at);
|
||||||
console.log("AXE enabled.");
|
console.log("AXE enabled.");
|
||||||
|
|
||||||
function verify(dht, msg) {
|
function verify(dht, msg){
|
||||||
var S = (+new Date);
|
var S = (+new Date);
|
||||||
var puts = Object.keys(msg.put);
|
var puts = Object.keys(msg.put);
|
||||||
var soul = puts[0]; /// TODO: verify all souls in puts. Copy the msg only with subscribed souls?
|
var soul = puts[0]; /// TODO: verify all souls in puts. Copy the msg only with subscribed souls?
|
||||||
var subs = dht(soul);
|
var subs = dht(soul);
|
||||||
if (!subs) { return; }
|
if (!subs) { return; }
|
||||||
var tmp = [];
|
var tmp = [];
|
||||||
Gun.obj.map(subs.split(','), function(pid) {
|
(subs.split(',')||[]).forEach(function(pid){
|
||||||
if (pid in peers) {
|
if (pid in peers) {
|
||||||
tmp.push(pid);
|
tmp.push(pid);
|
||||||
mesh.say(msg, peers[pid]);
|
mesh.say(msg, peers[pid]);
|
||||||
@ -99,7 +96,7 @@
|
|||||||
}
|
}
|
||||||
// TODO: AXE NEEDS TO BE CHECKED FOR NEW CODE SYSTEM!!!!!!!!!!
|
// TODO: AXE NEEDS TO BE CHECKED FOR NEW CODE SYSTEM!!!!!!!!!!
|
||||||
|
|
||||||
var Rad = (Gun.window||{}).Radix || USE('./lib/radix', 1);
|
var Rad = (Gun.window||'').Radix || USE('./lib/radix', 1);
|
||||||
at.opt.dht = Rad();
|
at.opt.dht = Rad();
|
||||||
at.on('in', input);
|
at.on('in', input);
|
||||||
function input(msg){
|
function input(msg){
|
||||||
@ -134,9 +131,9 @@
|
|||||||
to.next(msg);
|
to.next(msg);
|
||||||
|
|
||||||
if (opt.rtc && msg.dht) {
|
if (opt.rtc && msg.dht) {
|
||||||
Gun.obj.map(msg.dht, function(pids, soul) {
|
Object.keys(msg.dht).forEach(function(soul, pids) { pids = msg.dht[soul];
|
||||||
dht(soul, pids);
|
dht(soul, pids);
|
||||||
Gun.obj.map(pids.split(','), function(pid) {
|
(pids.split(',')||[]).forEach(function(pid) {
|
||||||
/// TODO: here we can put an algorithm of who must connect?
|
/// TODO: here we can put an algorithm of who must connect?
|
||||||
if (!pid || pid in opt.peers || pid === opt.pid || opt.announce[pid]) { return; }
|
if (!pid || pid in opt.peers || pid === opt.pid || opt.announce[pid]) { return; }
|
||||||
opt.announce[pid] = true; /// To try only one connection to the same peer.
|
opt.announce[pid] = true; /// To try only one connection to the same peer.
|
||||||
@ -152,7 +149,7 @@
|
|||||||
var tmp = msg.opt;
|
var tmp = msg.opt;
|
||||||
if(!tmp){ return }
|
if(!tmp){ return }
|
||||||
tmp = tmp.peers;
|
tmp = tmp.peers;
|
||||||
if(!tmp || !Gun.text.is(tmp)){ return }
|
if(!tmp || 'string' != typeof tmp){ return }
|
||||||
if(axe.up[tmp] || 6 <= Object.keys(axe.up).length){ return }
|
if(axe.up[tmp] || 6 <= Object.keys(axe.up).length){ return }
|
||||||
var o = tmp; //{peers: tmp};
|
var o = tmp; //{peers: tmp};
|
||||||
at.$.opt(o);
|
at.$.opt(o);
|
||||||
@ -182,7 +179,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(msg.get){ mesh.say(msg, axe.up) } // always send gets up!
|
if(msg.get){ mesh.say(msg, axe.up) } // always send gets up! // send gets up to only rad's up
|
||||||
if(msg.get && (tmp = route(msg.get))){
|
if(msg.get && (tmp = route(msg.get))){
|
||||||
var hash = tmp; //Gun.obj.hash(msg.get);
|
var hash = tmp; //Gun.obj.hash(msg.get);
|
||||||
var routes = axe.routes || (axe.routes = {}); // USE RAD INSTEAD! TMP TESTING!
|
var routes = axe.routes || (axe.routes = {}); // USE RAD INSTEAD! TMP TESTING!
|
||||||
@ -221,11 +218,11 @@
|
|||||||
var S = (+new Date); // STATS!
|
var S = (+new Date); // STATS!
|
||||||
var routes = axe.routes || (axe.routes = {}); // USE RAD INSTEAD! TMP TESTING!
|
var routes = axe.routes || (axe.routes = {}); // USE RAD INSTEAD! TMP TESTING!
|
||||||
var peers = {};
|
var peers = {};
|
||||||
Gun.obj.map(msg.put, function(node, soul){
|
Object.keys(msg.put).forEach(function(soul, node){ node = msg.put[soul];
|
||||||
var hash = soul; //Gun.obj.hash({'#': soul});
|
var hash = soul; //Gun.obj.hash({'#': soul});
|
||||||
var to = routes[hash];
|
var to = routes[hash];
|
||||||
if(!to){ return }
|
if(!to){ return }
|
||||||
Gun.obj.to(to, peers);
|
Object.keys(to).forEach(function(k){ peers[k] = to[k] });
|
||||||
});
|
});
|
||||||
console.STAT && (ST = +new Date - S) > 9 && console.STAT(S, ST, 'axe put');
|
console.STAT && (ST = +new Date - S) > 9 && console.STAT(S, ST, 'axe put');
|
||||||
mesh.say(msg, peers);
|
mesh.say(msg, peers);
|
||||||
@ -306,6 +303,7 @@
|
|||||||
peer.url = '';
|
peer.url = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var obj_map = function(o, f, r){
|
var obj_map = function(o, f, r){
|
||||||
for(var k in o){
|
for(var k in o){
|
||||||
if(!o.hasOwnProperty(k)){ continue }
|
if(!o.hasOwnProperty(k)){ continue }
|
||||||
|
@ -127,7 +127,7 @@
|
|||||||
$(document).on('keyup', '.thought__input', function () {
|
$(document).on('keyup', '.thought__input', function () {
|
||||||
var input = $(this), id = input.attr('id');
|
var input = $(this), id = input.attr('id');
|
||||||
if (!id) {
|
if (!id) {
|
||||||
input.attr('id', id = Gun.text.random());
|
input.attr('id', id = String.random());
|
||||||
}
|
}
|
||||||
typing = id;
|
typing = id;
|
||||||
clearTimeout(throttle);
|
clearTimeout(throttle);
|
||||||
|
492
gun.js
492
gun.js
@ -294,14 +294,14 @@
|
|||||||
function put(msg){
|
function put(msg){
|
||||||
if(!msg){ return }
|
if(!msg){ return }
|
||||||
var ctx = msg._||'', root = ctx.root = ((ctx.$ = msg.$||'')._||'').root;
|
var ctx = msg._||'', root = ctx.root = ((ctx.$ = msg.$||'')._||'').root;
|
||||||
/*if(msg['@'] && !ctx.me){ // TODO: WARNING! This will prevent relays from caching!
|
if(msg['@'] && ctx.faith && !ctx.miss){ // TODO: AXE may split/route based on 'put' what should we do here? Detect @ in AXE?
|
||||||
msg.out = universe;
|
msg.out = universe;
|
||||||
root.on('out', msg);
|
root.on('out', msg);
|
||||||
return;
|
return;
|
||||||
}*/
|
}
|
||||||
var put = msg.put;
|
var put = msg.put;
|
||||||
var DBG = ctx.DBG = msg.DBG;
|
var DBG = ctx.DBG = msg.DBG;
|
||||||
if(put['#'] && put['.']){ root && root.on('put', msg); return } // TODO: BUG! This needs to call HAM instead.
|
if(put['#'] && put['.']){ /*root && root.on('put', msg);*/ return } // TODO: BUG! This needs to call HAM instead.
|
||||||
DBG && (DBG.p = S);
|
DBG && (DBG.p = S);
|
||||||
ctx['#'] = msg['#'];
|
ctx['#'] = msg['#'];
|
||||||
ctx.msg = msg;
|
ctx.msg = msg;
|
||||||
@ -315,6 +315,9 @@
|
|||||||
ctx.stun--; // TODO: 'forget' feature in SEA tied to this, bad approach, but hacked in for now. Any changes here must update there.
|
ctx.stun--; // TODO: 'forget' feature in SEA tied to this, bad approach, but hacked in for now. Any changes here must update there.
|
||||||
ctx.hatch && ctx.hatch(); // TODO: rename/rework how put & this interact.
|
ctx.hatch && ctx.hatch(); // TODO: rename/rework how put & this interact.
|
||||||
//fire(ctx); // ABC
|
//fire(ctx); // ABC
|
||||||
|
if(err || ctx.err || msg.err){ return }
|
||||||
|
msg.out = universe;
|
||||||
|
root.on('out', msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!(node = put[soul])){ err = ERR+cut(soul)+"no node." } else
|
if(!(node = put[soul])){ err = ERR+cut(soul)+"no node." } else
|
||||||
@ -339,19 +342,13 @@
|
|||||||
if((kl = kl.slice(i)).length){ turn(pop); return }
|
if((kl = kl.slice(i)).length){ turn(pop); return }
|
||||||
++ni; kl = null; pop(o);
|
++ni; kl = null; pop(o);
|
||||||
}());
|
}());
|
||||||
|
|
||||||
/*DBG && (DBG.pe = +new Date);
|
|
||||||
if(console.STAT){ console.STAT(S, +new Date - S, 'mix');console.STAT(S, ctx.lot.s, 'mix #') }
|
|
||||||
if(ctx.err = err){ root.on('in', {'@': id, err: Gun.log(err)}); return }
|
|
||||||
if(!(--ctx.lot.more)){ fire(ctx) } // if synchronous.
|
|
||||||
if(!ctx.stun && !msg['@']){ root.on('in', {'@': id, ok: -1}) } // in case no diff sent to storage, etc., still ack.*/
|
|
||||||
} Gun.on.put = put;
|
} Gun.on.put = put;
|
||||||
function ham(val, key, soul, state, msg){
|
function ham(val, key, soul, state, msg){
|
||||||
var ctx = msg._||'', root = ctx.root, graph = root.graph, lot;
|
var ctx = msg._||'', root = ctx.root, graph = root.graph, lot;
|
||||||
var vertex = graph[soul] || empty, was = state_is(vertex, key, 1), known = vertex[key];
|
var vertex = graph[soul] || empty, was = state_is(vertex, key, 1), known = vertex[key];
|
||||||
var now = State(),u;
|
var now = State(),u;
|
||||||
if(state > now){ setTo; return }
|
if(state > now){ setTo; return }
|
||||||
if(state < was){ old; if(!ctx.miss){ return } } // but some chains have a cache miss that need to re-fire. // TODO: Improve in future. // for AXE this would reduce rebroadcast, but GUN does it on message forwarding.
|
if(state < was){ /*old;*/ if(!ctx.miss){ return } } // but some chains have a cache miss that need to re-fire. // TODO: Improve in future. // for AXE this would reduce rebroadcast, but GUN does it on message forwarding.
|
||||||
if(!ctx.faith){ // TODO: BUG? Can this be used for cache miss as well?
|
if(!ctx.faith){ // TODO: BUG? Can this be used for cache miss as well?
|
||||||
if(state === was && (val === known || L(val) <= L(known))){ return } // same
|
if(state === was && (val === known || L(val) <= L(known))){ return } // same
|
||||||
}
|
}
|
||||||
@ -366,8 +363,6 @@
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}*/
|
}*/
|
||||||
//(lot = ctx.lot||'').s++; lot.more++;
|
|
||||||
//(ctx.stun || (ctx.stun = {}))[soul+key] = 1;
|
|
||||||
//ctx.stun++; // TODO: 'forget' feature in SEA tied to this, bad approach, but hacked in for now. Any changes here must update there.
|
//ctx.stun++; // TODO: 'forget' feature in SEA tied to this, bad approach, but hacked in for now. Any changes here must update there.
|
||||||
var aid = msg['#']+ctx.stun++, id = {toString: function(){ return aid }, _: ctx}; // this *trick* makes it compatible between old & new versions.
|
var aid = msg['#']+ctx.stun++, id = {toString: function(){ return aid }, _: ctx}; // this *trick* makes it compatible between old & new versions.
|
||||||
var DBG = ctx.DBG; DBG && (DBG.ph = DBG.ph || +new Date);
|
var DBG = ctx.DBG; DBG && (DBG.ph = DBG.ph || +new Date);
|
||||||
@ -376,66 +371,25 @@
|
|||||||
function map(msg){
|
function map(msg){
|
||||||
var DBG; if(DBG = (msg._||'').DBG){ DBG.pa = +new Date; DBG.pm = DBG.pm || +new Date}
|
var DBG; if(DBG = (msg._||'').DBG){ DBG.pa = +new Date; DBG.pm = DBG.pm || +new Date}
|
||||||
var eve = this, root = eve.as, graph = root.graph, ctx = msg._, put = msg.put, soul = put['#'], key = put['.'], val = put[':'], state = put['>'], id = msg['#'], tmp;
|
var eve = this, root = eve.as, graph = root.graph, ctx = msg._, put = msg.put, soul = put['#'], key = put['.'], val = put[':'], state = put['>'], id = msg['#'], tmp;
|
||||||
graph[soul] = state_ify(graph[soul], key, state, val, soul); // TODO: Only put in graph if subscribed? Relays vs Browsers?
|
graph[soul] = state_ify(graph[soul], key, state, val, soul);
|
||||||
// /* manhattan:
|
|
||||||
//_.on('in', {$: $, get: soul, put: state_ify({}, key, state, tmp, soul)});
|
|
||||||
if(tmp = (root.next||'')[soul]){ tmp.on('in', msg) }
|
if(tmp = (root.next||'')[soul]){ tmp.on('in', msg) }
|
||||||
eve.to.next(msg);
|
eve.to.next(msg);
|
||||||
if(!(--ctx.stun)){ // A312020 ? // no need to wait for map, can do on put end?
|
--ctx.stun;
|
||||||
tmp = ctx.msg;
|
|
||||||
tmp.out = universe;
|
|
||||||
root.on('out', tmp);
|
|
||||||
}
|
|
||||||
return; // eom*/
|
|
||||||
_.put = state_ify(_.put, key, state, tmp = (u !== (tmp = put['=']))? tmp : val, soul);
|
|
||||||
chain(ctx, soul, key, (u !== (tmp = put['=']))? tmp : val, state); // TODO: This should NOT be how the API works, this should be done at an extension layer, but hacky solution to migrate with old code for now.
|
|
||||||
if((tmp = ctx.out) && (tmp = tmp.put)){
|
|
||||||
tmp[soul] = state_ify(tmp[soul], key, state, val, soul); // TODO: Hacky, fix & come back later, for actual pushing messages.
|
|
||||||
}
|
|
||||||
//if(!(--ctx.lot.more)){ fire(ctx) }
|
|
||||||
if(!(--ctx.stun)){ fire(ctx) }
|
|
||||||
eve.to.next(msg);
|
|
||||||
}
|
}
|
||||||
function chain(ctx, soul, key,val, state){
|
function ack(msg){ // aggregate ACKs.
|
||||||
var root = ctx.root, put, tmp;
|
var id = msg['@'] || '', root = (msg.$._||'').root, tmp;
|
||||||
(root.opt||'').super && root.$.get(soul); // I think we need super for now, but since we are rewriting, should consider getting rid of it.
|
if(msg.err && root && root.dup.s[id]){ console.log('add err to original message to not send') }
|
||||||
if(!root || !(tmp = root.next) || !(tmp = tmp[soul]) || !tmp.$){ return }
|
if(!(tmp = id._)){ /*console.log("TODO: handle ack id.");*/ return }
|
||||||
(put = ctx.put || (ctx.put = {}))[soul] = state_ify(put[soul], key, state, val, soul);
|
tmp.acks = (tmp.acks||0) + 1;
|
||||||
tmp.put = state_ify(tmp.put, key, state, val, soul);
|
if(0 == tmp.stun && tmp.acks == tmp.all){ // TODO: if ack is synchronous this may not work?
|
||||||
}
|
root && root.on('in', {'@': tmp['#'], err: msg.err, ok: 'shard'});
|
||||||
function fire(ctx){
|
|
||||||
if(ctx.err){ return }
|
|
||||||
var stop = {};
|
|
||||||
var root = ((ctx.$||'')._||'').root, next = (root||'').next||'', put = ctx.put, tmp;
|
|
||||||
var S = +new Date;
|
|
||||||
//Gun.graph.is(put, function(node, soul){
|
|
||||||
for(var soul in put){ var node = put[soul]; // Gun.obj.native() makes this safe.
|
|
||||||
if(!(tmp = next[soul]) || !tmp.$){ continue }
|
|
||||||
root.stop = stop; // temporary fix till a better solution?
|
|
||||||
tmp.on('in', {$: tmp.$, get: soul, put: node});
|
|
||||||
root.stop = null; // temporary fix till a better solution?
|
|
||||||
}
|
}
|
||||||
//console.log("fire:", +new Date - S);
|
|
||||||
console.STAT && console.STAT(S, +new Date - S, 'fire');
|
|
||||||
ctx.DBG && (ctx.DBG.f = +new Date);
|
|
||||||
if(!(tmp = ctx.msg)){ return }
|
|
||||||
tmp.out = universe;
|
|
||||||
//console.log("PUT:", +new Date - ctx.START, ctx.lot); ctx.START = null;
|
|
||||||
root.on('out', tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var ERR = "Error: Invalid graph!";
|
var ERR = "Error: Invalid graph!";
|
||||||
var cut = function(s){ return " '"+(''+s).slice(0,9)+"...' " }
|
var cut = function(s){ return " '"+(''+s).slice(0,9)+"...' " }
|
||||||
var L = JSON.stringify, MD = 2147483647, State = Gun.state;
|
var L = JSON.stringify, MD = 2147483647, State = Gun.state;
|
||||||
|
|
||||||
function ack(msg){ // aggregate ACKs.
|
|
||||||
var id = msg['@'] || '', tmp;
|
|
||||||
if(!(tmp = id._)){ /*console.log("TODO: handle ack id.");*/ return }
|
|
||||||
tmp.acks = (tmp.acks||0) + 1;
|
|
||||||
if(0 == tmp.stun && tmp.acks == tmp.all){ // TODO: if ack is synchronous this may not work?
|
|
||||||
console.log("@@@@@@ DONE @@@@@@", id);
|
|
||||||
((msg.$||'')._||'').root.on('in', {'@': tmp['#'], err: msg.err, ok: 'shard'});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}());
|
}());
|
||||||
|
|
||||||
;(function(){
|
;(function(){
|
||||||
@ -443,6 +397,7 @@
|
|||||||
var root = gun._, get = msg.get, soul = get['#'], node = root.graph[soul], has = get['.'], tmp;
|
var root = gun._, get = msg.get, soul = get['#'], node = root.graph[soul], has = get['.'], tmp;
|
||||||
var next = root.next || (root.next = {}), at = next[soul];
|
var next = root.next || (root.next = {}), at = next[soul];
|
||||||
// queue concurrent GETs?
|
// queue concurrent GETs?
|
||||||
|
// TODO: consider tagging original message into dup for DAM.
|
||||||
var ctx = msg._||'', DBG = ctx.DBG = msg.DBG;
|
var ctx = msg._||'', DBG = ctx.DBG = msg.DBG;
|
||||||
DBG && (DBG.g = +new Date);
|
DBG && (DBG.g = +new Date);
|
||||||
//console.log("GET", get);
|
//console.log("GET", get);
|
||||||
@ -453,45 +408,25 @@
|
|||||||
// If we have a key in-memory, do we really need to fetch?
|
// If we have a key in-memory, do we really need to fetch?
|
||||||
// Maybe... in case the in-memory key we have is a local write
|
// Maybe... in case the in-memory key we have is a local write
|
||||||
// we still need to trigger a pull/merge from peers.
|
// we still need to trigger a pull/merge from peers.
|
||||||
} //else {
|
}
|
||||||
//Gun.window? Gun.obj.copy(node) : node; // HNPERF: If !browser bump Performance? Is this too dangerous to reference root graph? Copy / shallow copy too expensive for big nodes. Gun.obj.to(node); // 1 layer deep copy // Gun.obj.copy(node); // too slow on big nodes
|
//Gun.window? Gun.obj.copy(node) : node; // HNPERF: If !browser bump Performance? Is this too dangerous to reference root graph? Copy / shallow copy too expensive for big nodes. Gun.obj.to(node); // 1 layer deep copy // Gun.obj.copy(node); // too slow on big nodes
|
||||||
var ack = msg['#'], id = text_rand(9), keys = Object.keys(node||''), soul = ((node||'')._||'')['#'];
|
var ack = msg['#'], id = text_rand(9), keys = Object.keys(node||''), soul = ((node||'')._||'')['#'];
|
||||||
// PERF: Consider commenting this out to force disk-only reads for perf testing?
|
// PERF: Consider commenting this out to force disk-only reads for perf testing?
|
||||||
node && (function got(){
|
node && (function got(){
|
||||||
var i = 0, k, put = {};
|
var i = 0, k, put = {};
|
||||||
while(i < 9 && (k = keys[i++])){
|
while(i < 9 && (k = keys[i++])){
|
||||||
state_ify(put, k, state_is(node, k), node[k], soul);
|
state_ify(put, k, state_is(node, k), node[k], soul);
|
||||||
}
|
}
|
||||||
keys = keys.slice(i);
|
keys = keys.slice(i);
|
||||||
(tmp = {})[soul] = put; put = tmp;
|
(tmp = {})[soul] = put; put = tmp;
|
||||||
var faith = function(){}; faith.ram = faith.faith = true; // HNPERF: We're testing performance improvement by skipping going through security again, but this should be audited.
|
var faith = function(){}; faith.ram = faith.faith = true; // HNPERF: We're testing performance improvement by skipping going through security again, but this should be audited.
|
||||||
tmp = keys.length;
|
tmp = keys.length;
|
||||||
DBG && (DBG.ga = +new Date);
|
DBG && (DBG.ga = +new Date);
|
||||||
root.on('in', {'@': ack, '#': id, put: put, '%': (tmp? (id = text_rand(9)) : u), ram: 1, $: gun, _: faith});
|
root.on('in', {'@': ack, '#': id, put: put, '%': (tmp? (id = text_rand(9)) : u), ram: 1, $: gun, _: faith});
|
||||||
if(!tmp){ return }
|
if(!tmp){ return }
|
||||||
setTimeout.turn(got);
|
setTimeout.turn(got);
|
||||||
}());
|
}());
|
||||||
root.on('get', msg); // send GET to storage adapters.
|
root.on('get', msg); // send GET to storage adapters.
|
||||||
return;
|
|
||||||
//}
|
|
||||||
/*//console.log("GOT", Object.keys(node).length);
|
|
||||||
(tmp = {})[node._['#']] = node; node = tmp;
|
|
||||||
tmp = (at||empty).ack;
|
|
||||||
var faith = function(){}; faith.ram = faith.faith = true; // HNPERF: We're testing performance improvement by skipping going through security again, but this should be audited.
|
|
||||||
faith.$ = msg.$;
|
|
||||||
DBG && (DBG.ga = +new Date);
|
|
||||||
root.on('in', {
|
|
||||||
'@': msg['#'],
|
|
||||||
put: node,
|
|
||||||
ram: 1,
|
|
||||||
$: gun,
|
|
||||||
_: faith
|
|
||||||
});
|
|
||||||
DBG && (DBG.gm = +new Date);
|
|
||||||
//if(0 < tmp){ return }
|
|
||||||
root.on('get', msg);
|
|
||||||
DBG && (DBG.gd = +new Date);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
|
|
||||||
@ -690,13 +625,14 @@
|
|||||||
}
|
}
|
||||||
if((msg.seen||'')[cat.id]){ return } (msg.seen || (msg.seen = function(){}))[cat.id] = cat;
|
if((msg.seen||'')[cat.id]){ return } (msg.seen || (msg.seen = function(){}))[cat.id] = cat;
|
||||||
|
|
||||||
if(cat.ask && key){
|
//if(cat.ask && key){
|
||||||
if(cat.soul && state >= state_is(root.graph[soul], key)){ // faster than HAM
|
if(key){
|
||||||
|
if(cat.soul && cat.ask && state >= state_is(root.graph[soul], key)){ // faster than HAM
|
||||||
cat.put = state_ify(cat.put, key, state, change, soul);
|
cat.put = state_ify(cat.put, key, state, change, soul);
|
||||||
}
|
}
|
||||||
if(cat.has && at.soul){
|
if(cat.has && at.soul){
|
||||||
cat.put = at.put;
|
cat.put = at.put;
|
||||||
} else
|
}
|
||||||
if(cat.has && at === cat && state >= state_is(root.graph[soul], key)){ // faster than HAM
|
if(cat.has && at === cat && state >= state_is(root.graph[soul], key)){ // faster than HAM
|
||||||
cat.put = change;
|
cat.put = change;
|
||||||
}
|
}
|
||||||
@ -750,225 +686,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
return;
|
|
||||||
return;
|
|
||||||
if(cat.soul || (cat.has && cat.link)){
|
|
||||||
if((tmp = cat.next) && (tmp = tmp[key])){ // Then make sure to call that sub property's chain if it exists.
|
|
||||||
tmp.on('in', msg);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else
|
|
||||||
if(cat.has){
|
|
||||||
if('string' == typeof (rel = valid(change))){
|
|
||||||
console.log("!!!!!!!!!!!!!!!!!!!!!!!", cat.get, cat, at);
|
|
||||||
tmp = root.$.get(cat.link = rel)._; // grab what we're linking to.
|
|
||||||
(tmp.echo || (tmp.echo = {}))[cat.id] = cat; // add ourselves to it.
|
|
||||||
//console.log("We want to be echo to", at.link, at.get, at.id);
|
|
||||||
setTimeout.each(Object.keys(cat.ask||''), function(get, sat){ // if sub chains are asking for data.
|
|
||||||
if(!(sat = cat.ask[get])){ return }
|
|
||||||
sat.on('out', {get: {'#': rel, '.': get}}); // go get it.
|
|
||||||
},0,99);
|
|
||||||
return;
|
|
||||||
} else
|
|
||||||
if(!rel){ // also (B)
|
|
||||||
return;
|
|
||||||
} else { // (C)
|
|
||||||
// TODO: If any below me, we need to clear it out.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return; // */
|
|
||||||
var eve = this, cat = eve.as, root = cat.root, gun = msg.$, at = (gun||empty)._ || empty, change = msg.put, rel, tmp;
|
|
||||||
if(cat.get && msg.get !== cat.get){
|
|
||||||
tmp = {get: cat.get}; Object.keys(msg).forEach(function(k){ tmp[k] = msg[k] });
|
|
||||||
}
|
|
||||||
if(cat.has && at !== cat){
|
|
||||||
tmp = {$: cat.$}; Object.keys(msg).forEach(function(k){ tmp[k] = msg[k] });
|
|
||||||
if(at.ack){
|
|
||||||
cat.ack = at.ack;
|
|
||||||
//cat.ack = cat.ack || at.ack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(u === change){
|
|
||||||
tmp = at.put;
|
|
||||||
eve.to.next(msg);
|
|
||||||
if(cat.soul){ return } // TODO: BUG, I believee the fresh input refactor caught an edge case that a `gun.get('soul').get('key')` that points to a soul that doesn't exist will not trigger val/get etc.
|
|
||||||
if(u === tmp && u !== at.put){ return }
|
|
||||||
echo(cat, msg, eve);
|
|
||||||
if(cat.has){
|
|
||||||
not(cat, msg);
|
|
||||||
}
|
|
||||||
delete (at.echo||{})[cat.id];
|
|
||||||
delete (cat.map||{})[at.id];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(cat.soul){
|
|
||||||
eve.to.next(msg);
|
|
||||||
echo(cat, msg, eve);
|
|
||||||
if(cat.next){ Object.keys(change).forEach(map, {msg: msg, cat: cat}) }
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//if(!(rel = Gun.val.link.is(change))){
|
|
||||||
if('string' != typeof (rel = valid(change))){
|
|
||||||
if(valid(change)){
|
|
||||||
if(cat.has || cat.soul){
|
|
||||||
not(cat, msg);
|
|
||||||
} else
|
|
||||||
if(at.has || at.soul){
|
|
||||||
(at.echo || (at.echo = {}))[cat.id] = at.echo[at.id] || cat;
|
|
||||||
(cat.map || (cat.map = {}))[at.id] = cat.map[at.id] || {at: at};
|
|
||||||
//if(u === at.put){ return } // Not necessary but improves performance. If we have it but at does not, that means we got things out of order and at will get it. Once at gets it, it will tell us again.
|
|
||||||
}
|
|
||||||
eve.to.next(msg);
|
|
||||||
echo(cat, msg, eve);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(cat.has && at !== cat && obj_has(at, 'put')){
|
|
||||||
cat.put = at.put;
|
|
||||||
};
|
|
||||||
if((rel = ((change||'')._||'')['#']) && at.has){
|
|
||||||
at.put = (cat.root.$.get(rel)._).put;
|
|
||||||
}
|
|
||||||
tmp = (root.stop || {})[at.id];
|
|
||||||
//if(tmp && tmp[cat.id]){ } else {
|
|
||||||
eve.to.next(msg);
|
|
||||||
//}
|
|
||||||
relate(cat, msg, at, rel);
|
|
||||||
echo(cat, msg, eve);
|
|
||||||
if(cat.next){ Object.keys(change).forEach(map, {msg: msg, cat: cat}) }
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var was = root.stop;
|
|
||||||
tmp = root.stop || {};
|
|
||||||
tmp = tmp[at.id] || (tmp[at.id] = {});
|
|
||||||
//if(tmp[cat.id]){ return }
|
|
||||||
tmp.is = tmp.is || at.put;
|
|
||||||
tmp[cat.id] = at.put || true;
|
|
||||||
//if(root.stop){
|
|
||||||
eve.to.next(msg)
|
|
||||||
//}
|
|
||||||
relate(cat, msg, at, rel);
|
|
||||||
echo(cat, msg, eve);
|
|
||||||
}
|
|
||||||
function node(msg){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function relate(at, msg, from, rel){
|
|
||||||
if(!rel || '_' === at.get){ return }
|
|
||||||
var tmp = (at.root.$.get(rel)._);
|
|
||||||
if(at.has){
|
|
||||||
from = tmp;
|
|
||||||
} else
|
|
||||||
if(from.has){
|
|
||||||
relate(from, msg, from, rel);
|
|
||||||
}
|
|
||||||
if(from === at){ return }
|
|
||||||
if(!from.$){ from = {} }
|
|
||||||
(from.echo || (from.echo = {}))[at.id] = from.echo[at.id] || at;
|
|
||||||
if(at.has && !(at.map||empty)[from.id]){ // if we haven't seen this before.
|
|
||||||
not(at, msg);
|
|
||||||
}
|
|
||||||
tmp = from.id? ((at.map || (at.map = {}))[from.id] = at.map[from.id] || {at: from}) : {};
|
|
||||||
if(rel === tmp.link){
|
|
||||||
if(!(tmp.pass || at.pass)){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(at.pass){
|
|
||||||
Object.keys(at.map).forEach(function(i){ var tmp = at.map[i]; tmp.pass = true })
|
|
||||||
delete at.pass;
|
|
||||||
}
|
|
||||||
if(tmp.pass){ delete tmp.pass; }
|
|
||||||
if(at.has){ at.link = rel }
|
|
||||||
ask(at, tmp.link = rel);
|
|
||||||
}
|
|
||||||
function echo(at, msg, ev){
|
|
||||||
if(!at.echo){ return } // || node_ === at.get ?
|
|
||||||
//if(at.has){ msg = obj_to(msg, {event: ev}) }
|
|
||||||
Object.keys(at.echo).forEach(function(k){ var to = at.echo[k];
|
|
||||||
if(!to || !to.on){ return }
|
|
||||||
to.on('in', msg);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function map(key){ // Map over only the changes on every update.
|
|
||||||
var cat = this.cat, next = cat.next || empty, via = this.msg, data = via.put[key], chain, at, tmp;
|
|
||||||
if('_' === key && !next[key]){ return }
|
|
||||||
if(!(at = next[key])){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//if(data && data[_soul] && (tmp = Gun.val.link.is(data)) && (tmp = (cat.root.$.get(tmp)._)) && obj_has(tmp, 'put')){
|
|
||||||
// data = tmp.put;
|
|
||||||
//}
|
|
||||||
if(at.has){
|
|
||||||
//if(!(data && data[_soul] && Gun.val.link.is(data) === Gun.node.soul(at.put))){
|
|
||||||
if(u === at.put || 'string' != typeof valid(data)){ // not a link!
|
|
||||||
at.put = data;
|
|
||||||
}
|
|
||||||
chain = at.$;
|
|
||||||
} else
|
|
||||||
if(tmp = via.$){
|
|
||||||
tmp = (chain = via.$.get(key))._;
|
|
||||||
if(u === tmp.put || 'string' != typeof valid(data)){
|
|
||||||
tmp.put = data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
at.on('in', {
|
|
||||||
put: data,
|
|
||||||
get: key,
|
|
||||||
$: chain,
|
|
||||||
via: via
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function not(at, msg){
|
|
||||||
if(!(at.has || at.soul)){ return }
|
|
||||||
var tmp = at.map, root = at.root;
|
|
||||||
at.map = null;
|
|
||||||
if(at.has){
|
|
||||||
if(at.dub && at.root.stop){ at.dub = null }
|
|
||||||
at.link = null;
|
|
||||||
}
|
|
||||||
//if(!root.now || !root.now[at.id]){
|
|
||||||
if(!at.pass){
|
|
||||||
if((!msg['@']) && null === tmp){ return }
|
|
||||||
//obj_del(at, 'pass');
|
|
||||||
}
|
|
||||||
//if(u === tmp && Gun.val.link.is(at.put)){ return } // This prevents the very first call of a thing from triggering a "clean up" call. // TODO: link.is(at.put) || !val.is(at.put) ?
|
|
||||||
if(u === tmp && 'string' == typeof valid(at.put)){ return } // This prevents the very first call of a thing from triggering a "clean up" call. // TODO: link.is(at.put) || !val.is(at.put) ?
|
|
||||||
Object.keys(tmp||{}).forEach(function(k){ var proxy = tmp[k];
|
|
||||||
if(!(proxy = proxy.at)){ return }
|
|
||||||
delete proxy.echo[at.id];
|
|
||||||
});
|
|
||||||
tmp = at.put;
|
|
||||||
//obj_map(at.next, function(neat, key){
|
|
||||||
Object.keys(at.next||{}).forEach(function(key){ var neat = at.next[key];
|
|
||||||
if(u === tmp && u !== at.put){ return true }
|
|
||||||
neat.put = u;
|
|
||||||
if(neat.ack){
|
|
||||||
neat.ack = -1; // Shouldn't this be reset to 0? If we do that, SEA test `set user ref should be found` fails, odd.
|
|
||||||
}
|
|
||||||
neat.on('in', {
|
|
||||||
get: key,
|
|
||||||
$: neat.$,
|
|
||||||
put: u
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function ask(at, soul){
|
|
||||||
var tmp = (at.root.$.get(soul)._), lex = at.lex;
|
|
||||||
if(at.ack || lex){
|
|
||||||
(lex = lex||{})['#'] = soul;
|
|
||||||
tmp.on('out', {get: lex});
|
|
||||||
if(!at.ask){ return } // TODO: PERFORMANCE? More elegant way?
|
|
||||||
}
|
|
||||||
tmp = at.ask; delete at['ask'];
|
|
||||||
Object.keys(tmp = tmp || at.next || {}).forEach(function(key){ var neat = tmp[key];
|
|
||||||
var lex = neat.lex || {}; lex['#'] = soul; lex['.'] = lex['.'] || key;
|
|
||||||
neat.on('out', {get: lex});
|
|
||||||
});
|
|
||||||
delete at['ask']; // TODO: PERFORMANCE? More elegant way?
|
|
||||||
}
|
}
|
||||||
function ack(msg, ev){
|
function ack(msg, ev){
|
||||||
// manhattan:
|
// manhattan:
|
||||||
@ -983,29 +700,9 @@
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
(msg._||{}).miss = 1;
|
||||||
Gun.on.put(msg);
|
Gun.on.put(msg);
|
||||||
return; // eom
|
return; // eom
|
||||||
var as = this.as, get = as.get||'', at = as.$._, tmp = (msg.put||'')[get['#']];
|
|
||||||
(msg._||{}).me = 1;
|
|
||||||
if(at.ack){ at.ack = (at.ack + 1) || 1; }
|
|
||||||
if(!msg.put || ('string' == typeof get['.'] && !obj_has(tmp, at.get))){
|
|
||||||
if(at.put !== u){ return }
|
|
||||||
at.on('in', {
|
|
||||||
get: at.get,
|
|
||||||
put: at.put = u,
|
|
||||||
$: at.$,
|
|
||||||
'@': msg['@']
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if('_' == get['.']){ // is this a security concern?
|
|
||||||
at.on('in', {get: at.get, put: Gun.val.link.ify(get['#']), $: at.$, '@': msg['@']});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(at.$ === (msg._||'').$){ // replying to self, for perf, skip ham/security tho needs audit.
|
|
||||||
(msg._).miss = (at.put === u);
|
|
||||||
}
|
|
||||||
Gun.on.put(msg);
|
|
||||||
}
|
}
|
||||||
var empty = {}, u, text_rand = String.random, valid = Gun.valid, obj_has = function(o, k){ return o && Object.prototype.hasOwnProperty.call(o, k) }, state = Gun.state, state_is = state.is, state_ify = state.ify;
|
var empty = {}, u, text_rand = String.random, valid = Gun.valid, obj_has = function(o, k){ return o && Object.prototype.hasOwnProperty.call(o, k) }, state = Gun.state, state_is = state.is, state_ify = state.ify;
|
||||||
})(USE, './chain');
|
})(USE, './chain');
|
||||||
@ -1153,18 +850,19 @@
|
|||||||
Gun.chain.put = function(data, cb, as){ // I rewrote it :)
|
Gun.chain.put = function(data, cb, as){ // I rewrote it :)
|
||||||
var gun = this, at = gun._, root = at.root;
|
var gun = this, at = gun._, root = at.root;
|
||||||
as = as || {};
|
as = as || {};
|
||||||
(root.stun = root.stun || {})[at.id] = (as.stun = as.stun || {});
|
(root.stun = root.stun || {})[at.id] = (as.stun = as.stun
|
||||||
|
|| ((root.stun._ = (root.stun._ || 0) + 1) && {}));
|
||||||
as.ack = as.ack || cb;
|
as.ack = as.ack || cb;
|
||||||
as.via = as.via || gun;
|
as.via = as.via || gun;
|
||||||
as.data = as.data || data;
|
as.data = as.data || data;
|
||||||
as.soul || (as.soul = at.soul || ('string' == typeof cb && cb));
|
as.soul || (as.soul = at.soul || ('string' == typeof cb && cb));
|
||||||
var s = as.state = as.state || Gun.state();
|
var s = as.state = as.state || Gun.state();
|
||||||
if(!as.soul){ return get(as), gun }
|
if(!as.soul){ return get(as), gun }
|
||||||
|
if('function' == typeof data){ data(function(d){ as.data = d; gun.put(u,u,as) }); return gun }
|
||||||
as.$ = root.$.get(as.soul);
|
as.$ = root.$.get(as.soul);
|
||||||
as.todo = [{it: as.data, ref: as.$}];
|
as.todo = [{it: as.data, ref: as.$}];
|
||||||
as.turn = as.turn || turn;
|
as.turn = as.turn || turn;
|
||||||
as.ran = as.ran || ran;
|
as.ran = as.ran || ran;
|
||||||
root.stun._ = (root.stun._ || 0) + 1;
|
|
||||||
var S = +new Date;
|
var S = +new Date;
|
||||||
(function walk(){
|
(function walk(){
|
||||||
var to = as.todo, at = to.pop(), d = at.it, v, k, cat, tmp, g;
|
var to = as.todo, at = to.pop(), d = at.it, v, k, cat, tmp, g;
|
||||||
@ -1174,7 +872,7 @@
|
|||||||
if(tmp.length){ to.push(at) }
|
if(tmp.length){ to.push(at) }
|
||||||
}
|
}
|
||||||
if(!(v = valid(d)) && !(g = Gun.is(d))){
|
if(!(v = valid(d)) && !(g = Gun.is(d))){
|
||||||
if(!Object.plain(d)){ (as.ack||noop).call(as, as.out = {err: Gun.log("Invalid data, " + typeof d + " at " + (as.path||[]).join('.'))}); return }
|
if(!Object.plain(d)){ (as.ack||noop).call(as, as.out = {err: Gun.log("Invalid data, " + typeof d + " at " + (as.path||[]).join('.'))}); return } // TODO: BUG! Clear out stun!
|
||||||
var seen = as.seen || (as.seen = []), i = seen.length;
|
var seen = as.seen || (as.seen = []), i = seen.length;
|
||||||
while(i--){ if(d === (tmp = seen[i]).it){ v = d = tmp.link; break } }
|
while(i--){ if(d === (tmp = seen[i]).it){ v = d = tmp.link; break } }
|
||||||
}
|
}
|
||||||
@ -1379,12 +1077,6 @@
|
|||||||
});
|
});
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
function map(msg){
|
|
||||||
if(!msg.put || Gun.valid(msg.put)){ this.to.next(msg); return }
|
|
||||||
if(this.as.nix){ this.off() } // TODO: Ugly hack!
|
|
||||||
Object.keys(msg.put).forEach(each, {at: this.as, msg: msg});
|
|
||||||
this.to.next(msg);
|
|
||||||
}
|
|
||||||
function map(msg){
|
function map(msg){
|
||||||
var cat = this, gun = msg.$, put = msg.put;
|
var cat = this, gun = msg.$, put = msg.put;
|
||||||
if(!put){ return }
|
if(!put){ return }
|
||||||
@ -1393,37 +1085,31 @@
|
|||||||
//console.log("let's go!!!!!!!!!!!!!!!!!", k, gun._.id, gun._.get);
|
//console.log("let's go!!!!!!!!!!!!!!!!!", k, gun._.id, gun._.get);
|
||||||
((tmp = gun.get(k)._).echo || (tmp.echo = {}))[cat.id] = tmp.echo[cat.id] || cat;
|
((tmp = gun.get(k)._).echo || (tmp.echo = {}))[cat.id] = tmp.echo[cat.id] || cat;
|
||||||
}
|
}
|
||||||
function each(k){
|
|
||||||
if('_' === k){ return }
|
|
||||||
var msg = this.msg, v = msg.put[k], gun = msg.$, at = gun._, cat = this.at, tmp = at.lex;
|
|
||||||
if(tmp && !Gun.text.match(k, tmp['.'] || tmp['#'] || tmp)){ return } // review?
|
|
||||||
((tmp = gun.get(k)._).echo || (tmp.echo = {}))[cat.id] = tmp.echo[cat.id] || cat;
|
|
||||||
}
|
|
||||||
var noop = function(){}, event = {stun: noop, off: noop}, u;
|
var noop = function(){}, event = {stun: noop, off: noop}, u;
|
||||||
})(USE, './map');
|
})(USE, './map');
|
||||||
|
|
||||||
;USE(function(module){
|
;USE(function(module){
|
||||||
var Gun = USE('./index');
|
var Gun = USE('./index');
|
||||||
Gun.chain.set = function(item, cb, opt){
|
Gun.chain.set = function(item, cb, opt){
|
||||||
var gun = this, soul;
|
var gun = this, soul, tmp;
|
||||||
cb = cb || function(){};
|
cb = cb || function(){};
|
||||||
opt = opt || {}; opt.item = opt.item || item;
|
opt = opt || {}; opt.item = opt.item || item;
|
||||||
if(soul = Gun.node.soul(item)){ item = Gun.obj.put({}, soul, Gun.val.link.ify(soul)) }
|
if(soul = ((item||'')._||'')['#']){ (item = {})[soul] = {'#': soul}; }
|
||||||
if(!Gun.is(item)){
|
if(!Gun.is(item)){
|
||||||
if(Gun.obj.is(item)){
|
if(Object.plain(item)){
|
||||||
//item = gun.back(-1).get(soul = soul || Gun.node.soul(item) || (gun.back('opt.uuid') || uuid)()).put(item);
|
|
||||||
soul = soul || Gun.node.soul(item) || uuid(); // this just key now, not a soul.
|
soul = soul || Gun.node.soul(item) || uuid(); // this just key now, not a soul.
|
||||||
}
|
}
|
||||||
return gun.get(soul || uuid()).put(item, cb, opt);
|
return gun.get(soul || uuid()).put(item, cb, opt);
|
||||||
}
|
}
|
||||||
item.get(function(soul, o, msg){
|
gun.put(function(go){
|
||||||
if(!soul && item._.stun){ item._.on('res', function(){ this.off(); gun.set(item, cb, opt) }); return }
|
item.get(function(soul, o, msg){ // TODO: BUG! We no longer have this option? & go error not handled?
|
||||||
if(!soul){ return cb.call(gun, {err: Gun.log('Only a node can be linked! Not "' + msg.put + '"!')}) }
|
if(!soul){ return cb.call(gun, {err: Gun.log('Only a node can be linked! Not "' + msg.put + '"!')}) }
|
||||||
gun.put(Gun.obj.put({}, soul, Gun.val.link.ify(soul)), cb, opt);
|
(tmp = {})[soul] = {'#': soul}; go(tmp);
|
||||||
},true);
|
},true);
|
||||||
|
})
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
function uuid(){ return Gun.state.lex() + Gun.text.random(7) }
|
function uuid(){ return Gun.state().toString(36).replace('.','') + String.random(7) }
|
||||||
})(USE, './set');
|
})(USE, './set');
|
||||||
|
|
||||||
;USE(function(module){
|
;USE(function(module){
|
||||||
@ -1510,7 +1196,7 @@
|
|||||||
|
|
||||||
;(function(){
|
;(function(){
|
||||||
var SMIA = 0;
|
var SMIA = 0;
|
||||||
var message, loop;
|
var loop;
|
||||||
mesh.hash = function(msg, peer){ var h, s, t;
|
mesh.hash = function(msg, peer){ var h, s, t;
|
||||||
json(msg.put, function hash(err, text){
|
json(msg.put, function hash(err, text){
|
||||||
var ss = (s || (s = t = text||'')).slice(0, 32768); // 1024 * 32
|
var ss = (s || (s = t = text||'')).slice(0, 32768); // 1024 * 32
|
||||||
@ -1522,7 +1208,6 @@
|
|||||||
delete msg._.$put;
|
delete msg._.$put;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
function each(peer){ mesh.say(message, peer) }
|
|
||||||
var say = mesh.say = function(msg, peer){ var tmp;
|
var say = mesh.say = function(msg, peer){ var tmp;
|
||||||
if((tmp = this) && (tmp = tmp.to) && tmp.next){ tmp.next(msg) } // compatible with middleware adapters.
|
if((tmp = this) && (tmp = tmp.to) && tmp.next){ tmp.next(msg) } // compatible with middleware adapters.
|
||||||
if(!msg){ return false }
|
if(!msg){ return false }
|
||||||
@ -1531,6 +1216,7 @@
|
|||||||
var meta = msg._||(msg._=function(){});
|
var meta = msg._||(msg._=function(){});
|
||||||
if(!(id = msg['#'])){ id = msg['#'] = String.random(9) }
|
if(!(id = msg['#'])){ id = msg['#'] = String.random(9) }
|
||||||
!loop && dup_track(id);//.it = it(msg); // track for 9 seconds, default. Earth<->Mars would need more! // always track, maybe move this to the 'after' logic if we split function.
|
!loop && dup_track(id);//.it = it(msg); // track for 9 seconds, default. Earth<->Mars would need more! // always track, maybe move this to the 'after' logic if we split function.
|
||||||
|
if(msg.put && msg.err){ return false } // stop relaying a invalid message, like failed SEA.
|
||||||
if(!(hash = msg['##']) && u !== msg.put && !meta.via && ack){ mesh.hash(msg, peer); return } // TODO: Should broadcasts be hashed?
|
if(!(hash = msg['##']) && u !== msg.put && !meta.via && ack){ mesh.hash(msg, peer); return } // TODO: Should broadcasts be hashed?
|
||||||
if(!(raw = meta.raw)){ mesh.raw(msg, peer); return }
|
if(!(raw = meta.raw)){ mesh.raw(msg, peer); return }
|
||||||
S && console.STAT && console.STAT(S, +new Date - S, 'say prep');
|
S && console.STAT && console.STAT(S, +new Date - S, 'say prep');
|
||||||
@ -1540,7 +1226,7 @@
|
|||||||
return false;
|
return false;
|
||||||
} // TODO: Temporary? If ack via trace has been lost, acks will go to all peers, which trashes browser bandwidth. Not relaying the ack will force sender to ask for ack again. Note, this is technically wrong for mesh behavior.
|
} // TODO: Temporary? If ack via trace has been lost, acks will go to all peers, which trashes browser bandwidth. Not relaying the ack will force sender to ask for ack again. Note, this is technically wrong for mesh behavior.
|
||||||
if(!peer && mesh.way){ return mesh.way(msg) }
|
if(!peer && mesh.way){ return mesh.way(msg) }
|
||||||
if(!peer || !peer.id){ message = msg;
|
if(!peer || !peer.id){
|
||||||
if(!Object.plain(peer || opt.peers)){ return false }
|
if(!Object.plain(peer || opt.peers)){ return false }
|
||||||
var P = opt.puff, ps = opt.peers, pl = Object.keys(peer || opt.peers || {});
|
var P = opt.puff, ps = opt.peers, pl = Object.keys(peer || opt.peers || {});
|
||||||
;(function go(){
|
;(function go(){
|
||||||
@ -1568,13 +1254,11 @@
|
|||||||
if(peer.batch){
|
if(peer.batch){
|
||||||
peer.tail = (tmp = peer.tail || 0) + raw.length;
|
peer.tail = (tmp = peer.tail || 0) + raw.length;
|
||||||
if(peer.tail <= opt.pack){
|
if(peer.tail <= opt.pack){
|
||||||
//peer.batch.push(raw);
|
|
||||||
peer.batch += (tmp?',':'')+raw;
|
peer.batch += (tmp?',':'')+raw;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
flush(peer);
|
flush(peer);
|
||||||
}
|
}
|
||||||
//peer.batch = [];
|
|
||||||
peer.batch = '['; // Prevents double JSON!
|
peer.batch = '['; // Prevents double JSON!
|
||||||
var S = +new Date, ST;
|
var S = +new Date, ST;
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
@ -1590,6 +1274,14 @@
|
|||||||
var meta = (msg._) || {}, put, tmp;
|
var meta = (msg._) || {}, put, tmp;
|
||||||
if(tmp = meta.raw){ return tmp }
|
if(tmp = meta.raw){ return tmp }
|
||||||
if('string' == typeof msg){ return msg }
|
if('string' == typeof msg){ return msg }
|
||||||
|
var hash = msg['##'], ack = msg['@'];
|
||||||
|
if(hash && ack){
|
||||||
|
dup_track(ack+hash);//.it = it(msg);
|
||||||
|
if((tmp = (dup.s[ack]||'').it) || ((tmp = mesh.last) && ack === tmp['#'])){
|
||||||
|
if(hash === tmp['##']){ return false }
|
||||||
|
tmp['##'] = hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(!msg.dam){
|
if(!msg.dam){
|
||||||
var i = 0, to = []; tmp = opt.peers;
|
var i = 0, to = []; tmp = opt.peers;
|
||||||
for(var k in tmp){ var p = tmp[k]; // TODO: Make it up peers instead!
|
for(var k in tmp){ var p = tmp[k]; // TODO: Make it up peers instead!
|
||||||
@ -1598,7 +1290,6 @@
|
|||||||
}
|
}
|
||||||
if(i > 1){ msg['><'] = to.join() }
|
if(i > 1){ msg['><'] = to.join() }
|
||||||
}
|
}
|
||||||
var hash = msg['##'], ack = msg['@'];
|
|
||||||
if(put = meta.$put){
|
if(put = meta.$put){
|
||||||
tmp = {}; Object.keys(msg).forEach(function(k){ tmp[k] = msg[k] });
|
tmp = {}; Object.keys(msg).forEach(function(k){ tmp[k] = msg[k] });
|
||||||
tmp.put = ':])([:';
|
tmp.put = ':])([:';
|
||||||
@ -1613,13 +1304,6 @@
|
|||||||
function res(err, raw){
|
function res(err, raw){
|
||||||
if(err){ return } // TODO: Handle!!
|
if(err){ return } // TODO: Handle!!
|
||||||
meta.raw = raw; //if(meta && (raw||'').length < (999 * 99)){ meta.raw = raw } // HNPERF: If string too big, don't keep in memory.
|
meta.raw = raw; //if(meta && (raw||'').length < (999 * 99)){ meta.raw = raw } // HNPERF: If string too big, don't keep in memory.
|
||||||
if(hash && ack){
|
|
||||||
dup_track(ack+hash);//.it = it(msg);
|
|
||||||
if((tmp = (dup.s[ack]||{}).it) || ((tmp = mesh.last) && ack === tmp['#'])){
|
|
||||||
if(hash === tmp['##']){ return false }
|
|
||||||
tmp['##'] = hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
say(msg, peer);
|
say(msg, peer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1638,6 +1322,7 @@
|
|||||||
}
|
}
|
||||||
// for now - find better place later.
|
// for now - find better place later.
|
||||||
function send(raw, peer){ try{
|
function send(raw, peer){ try{
|
||||||
|
//console.log(raw.slice(0,32));
|
||||||
var wire = peer.wire;
|
var wire = peer.wire;
|
||||||
if(peer.say){
|
if(peer.say){
|
||||||
peer.say(raw);
|
peer.say(raw);
|
||||||
@ -1663,9 +1348,9 @@
|
|||||||
if(!tmp.hied){ root.on(tmp.hied = 'hi', peer) }
|
if(!tmp.hied){ root.on(tmp.hied = 'hi', peer) }
|
||||||
// @rogowski I need this here by default for now to fix go1dfish's bug
|
// @rogowski I need this here by default for now to fix go1dfish's bug
|
||||||
tmp = peer.queue; peer.queue = [];
|
tmp = peer.queue; peer.queue = [];
|
||||||
(tmp||[]).forEach(function(msg){
|
setTimeout.each(tmp||[],function(msg){
|
||||||
send(msg, peer);
|
send(msg, peer);
|
||||||
});
|
},0,9);
|
||||||
//Type.obj.native && Type.obj.native(); // dirty place to check if other JS polluted.
|
//Type.obj.native && Type.obj.native(); // dirty place to check if other JS polluted.
|
||||||
}
|
}
|
||||||
mesh.bye = function(peer){
|
mesh.bye = function(peer){
|
||||||
@ -1705,39 +1390,14 @@
|
|||||||
root.on('hi', function(peer, tmp){ this.to.next(peer);
|
root.on('hi', function(peer, tmp){ this.to.next(peer);
|
||||||
if(!(tmp = peer.url) || !gets[tmp]){ return } delete gets[tmp];
|
if(!(tmp = peer.url) || !gets[tmp]){ return } delete gets[tmp];
|
||||||
if(opt.super){ return } // temporary (?) until we have better fix/solution?
|
if(opt.super){ return } // temporary (?) until we have better fix/solution?
|
||||||
Object.keys(root.next).forEach(function(soul){ var node = root.next[soul];
|
setTimeout.each(Object.keys(root.next), function(soul){ var node = root.next[soul];
|
||||||
tmp = {}; tmp[soul] = root.graph[soul];
|
tmp = {}; tmp[soul] = root.graph[soul]; tmp = String.hash(tmp); // TODO: BUG! This is broken.
|
||||||
mesh.say({'##': String.hash(tmp), get: {'#': soul}}, peer);
|
mesh.say({'##': tmp, get: {'#': soul}}, peer);
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
;(function(){
|
|
||||||
var $ = JSON.stringify, u;
|
|
||||||
|
|
||||||
Object.hash = function(obj, hash){
|
|
||||||
if(!hash && u === (obj = $(obj, sort))){ return }
|
|
||||||
return String.hash(hash || obj || '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function sort(k, v){ var tmp;
|
|
||||||
if(!(v instanceof Object)){ return v }
|
|
||||||
var S = +new Date;
|
|
||||||
Object.keys(v).sort().forEach(map, {to: tmp = {}, on: v});
|
|
||||||
console.STAT && console.STAT(S, +new Date - S, 'sort');
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
Object.hash.sort = sort;
|
|
||||||
|
|
||||||
function map(k){
|
|
||||||
this.to[k] = this.on[k];
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
|
|
||||||
function it(msg){ return msg || {_: msg._, '##': msg['##']} } // HNPERF: Only need some meta data, not full reference (took up too much memory). // HNPERF: Garrrgh! We add meta data to msg over time, copying the object happens to early.
|
|
||||||
|
|
||||||
var empty = {}, ok = true, u;
|
var empty = {}, ok = true, u;
|
||||||
|
|
||||||
try{ module.exports = Mesh }catch(e){}
|
try{ module.exports = Mesh }catch(e){}
|
||||||
@ -1795,9 +1455,9 @@
|
|||||||
open(peer);
|
open(peer);
|
||||||
}, wait);
|
}, wait);
|
||||||
}
|
}
|
||||||
var doc = 'undefined' !== typeof document && document;
|
var doc = (''+u !== typeof document) && document;
|
||||||
});
|
});
|
||||||
var noop = function(){};
|
var noop = function(){}, u;
|
||||||
})(USE, './websocket');
|
})(USE, './websocket');
|
||||||
|
|
||||||
;USE(function(module){
|
;USE(function(module){
|
||||||
|
@ -3,7 +3,7 @@ var config = {
|
|||||||
port: 8765,
|
port: 8765,
|
||||||
servers: 1,
|
servers: 1,
|
||||||
browsers: 3,
|
browsers: 3,
|
||||||
each: 1500,
|
each: 10000,
|
||||||
wait: 1,
|
wait: 1,
|
||||||
route: {
|
route: {
|
||||||
'/': __dirname + '/index.html',
|
'/': __dirname + '/index.html',
|
||||||
@ -90,6 +90,7 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
|
|||||||
// It has successfully launched.
|
// It has successfully launched.
|
||||||
test.done();
|
test.done();
|
||||||
});
|
});
|
||||||
|
//setInterval(function(){ console.log("CPU turns stacked:", setTimeout.turn.s.length) },1000);
|
||||||
}, {i: i += 1, config: config}));
|
}, {i: i += 1, config: config}));
|
||||||
});
|
});
|
||||||
// NOW, this is very important:
|
// NOW, this is very important:
|
||||||
@ -111,7 +112,8 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
|
|||||||
try{ localStorage.clear() }catch(e){}
|
try{ localStorage.clear() }catch(e){}
|
||||||
try{ indexedDB.deleteDatabase('radata') }catch(e){}
|
try{ indexedDB.deleteDatabase('radata') }catch(e){}
|
||||||
var env = test.props;
|
var env = test.props;
|
||||||
var gun = Gun('http://'+ env.config.IP + ':' + (env.config.port + 1) + '/gun');
|
//var gun = Gun('http://'+ env.config.IP + ':' + (env.config.port + 1) + '/gun');
|
||||||
|
var gun = Gun({localStorage: false, radisk: false, peers: 'http://'+ env.config.IP + ':' + (env.config.port + 1) + '/gun'});
|
||||||
window.gun = gun;
|
window.gun = gun;
|
||||||
window.ref = gun.get('chat');
|
window.ref = gun.get('chat');
|
||||||
}, {i: i += 1, config: config}));
|
}, {i: i += 1, config: config}));
|
||||||
@ -124,7 +126,7 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
|
|||||||
console.log("I AM CARL");
|
console.log("I AM CARL");
|
||||||
test.async();
|
test.async();
|
||||||
var rand = String.random || Gun.text.random;
|
var rand = String.random || Gun.text.random;
|
||||||
var i = 10000, chat = {}, S = Gun.state();
|
var i = test.props.each, chat = {}, S = Gun.state();
|
||||||
while(i--){
|
while(i--){
|
||||||
Gun.state.ify(chat, rand(9), S, rand(200), 'chat');
|
Gun.state.ify(chat, rand(9), S, rand(200), 'chat');
|
||||||
}
|
}
|
||||||
@ -132,23 +134,36 @@ describe("Load test "+ config.browsers +" browser(s) across "+ config.servers +"
|
|||||||
gun._.graph.chat = chat;
|
gun._.graph.chat = chat;
|
||||||
console.log(JSON.stringify(chat,null,2));
|
console.log(JSON.stringify(chat,null,2));
|
||||||
test.done();
|
test.done();
|
||||||
});
|
}, config);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Alice Asks for Chat", function(){
|
it("Alice Asks for Chat", function(){
|
||||||
return alice.run(function(test){
|
return alice.run(function(test){
|
||||||
console.log("I AM ALICE");
|
console.log("I AM ALICE");
|
||||||
test.async();
|
test.async();
|
||||||
var i = 0, S = +new Date;
|
var i = 0, t = test.props.each, tmp;
|
||||||
|
$('body').append("<div><i></i> / "+t+", seconds to first reply: <span></span>, CPU turns stacked: <u></u> <button onclick='this.innerText = Math.random();'>Can you click me?</button><input id='msg' style='width:100%;'><b></b></div>");
|
||||||
|
var $msg = $('#msg'), $i = $('i');
|
||||||
|
var V, I, S = +new Date, SS = S, tmp;
|
||||||
ref.map().once(function(v,k){
|
ref.map().once(function(v,k){
|
||||||
S && console.log('first:', +new Date - S) || (S = null);
|
S && console.log('first:', $('span').text(tmp = (+new Date - S)/1000) && tmp) || (S = null);
|
||||||
console.log(++i, "chat:",k,v);
|
if(!v){ no_data }
|
||||||
})
|
V = v;
|
||||||
|
I = ++i;
|
||||||
setTimeout(function(){
|
//console.log(i, "chat:",k,v);
|
||||||
//test.done();
|
if(i === t){
|
||||||
},1000);
|
$('b').text("seconds from start to end: " + ((+new Date - SS)/1000));
|
||||||
});
|
setTimeout(function(){ test.done() },100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
window.requestAnimationFrame = window.requestAnimationFrame || setTimeout;
|
||||||
|
window.requestAnimationFrame(function frame(){
|
||||||
|
window.requestAnimationFrame(frame, 16);
|
||||||
|
$msg.val(V);
|
||||||
|
$i.text(I);
|
||||||
|
}, 16);
|
||||||
|
setInterval(function(){ $('u').text(setTimeout.turn.s.length) },1000);
|
||||||
|
}, config);
|
||||||
});
|
});
|
||||||
|
|
||||||
/*it("Carl Recovers Chats", function(){
|
/*it("Carl Recovers Chats", function(){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user