diff --git a/examples/chat/index.html b/examples/chat/index.html
index c15f4229..8a3c74aa 100644
--- a/examples/chat/index.html
+++ b/examples/chat/index.html
@@ -181,7 +181,7 @@
$('.chat__message-input').val('').focus();
}
- chat.map().val(function (msg, id) {
+ chat.map().once(function (msg, id) {
if (!msg) { return }
var messageList = $('.chat__message-list');
var last = sort(msg.when, messageList.children('li').last());
diff --git a/gun.js b/gun.js
index fbb69a1e..0de16b90 100644
--- a/gun.js
+++ b/gun.js
@@ -189,18 +189,17 @@
}
var dt = dup.track = function(id){
var it = s[id] || (s[id] = {});
- it.was = +new Date;
+ it.was = dup.now = +new Date;
if(!dup.to){ dup.to = setTimeout(dup.drop, opt.age + 9) }
return it;
}
dup.drop = function(age){
- var now = +new Date;
- Object.keys(s).forEach(function(id){ var it = s[id];
- if(it && (age || opt.age) > (now - it.was)){ return }
- delete s[id];
- });
dup.to = null;
- console.STAT && (age = +new Date - now) > 9 && console.STAT(now, age, 'dup drop');
+ dup.now = +new Date;
+ setTimeout.each(Object.keys(s), function(id){ var it = s[id]; // TODO: .keys( is slow
+ if(it && (age || opt.age) > (dup.now - it.was)){ return }
+ delete s[id];
+ },0,99);
}
return dup;
}
@@ -288,6 +287,7 @@
DBG && (DBG.uc = +new Date);
eve.to.next(msg);
DBG && (DBG.ua = +new Date);
+ if(msg.nts || msg.NTS){ return } // TODO: This shouldn't be in core, but fast way to prevent NTS spread. Delete this line after all peers have upgraded to newer versions.
msg.out = universe; at.on('out', msg);
DBG && (DBG.ue = +new Date);
}
@@ -324,7 +324,7 @@
if(!(tmp = node._)){ err = ERR+cut(soul)+"no meta." } else
if(soul !== tmp['#']){ err = ERR+cut(soul)+"soul not same." } else
if(!(states = tmp['>'])){ err = ERR+cut(soul)+"no state." }
- kl = Object.keys(node||{});
+ kl = Object.keys(node||{}); // TODO: .keys( is slow
}
if(err){
console.log("handle error!", err) // handle!
@@ -411,7 +411,7 @@
}
//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||'')._||'')['#'];
- // 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? // TODO: .keys( is slow
node && (function got(){
var i = 0, k, put = {};
while(i < 9 && (k = keys[i++])){
@@ -618,7 +618,7 @@
var eve = this, cat = eve.as, root = cat.root, gun = msg.$ || (msg.$ = cat.$), at = (gun||'')._ || empty, tmp = msg.put||'', soul = tmp['#'], key = tmp['.'], change = tmp['=']||tmp[':'], state = tmp['>'] || -Infinity, link, sat;
if(tmp && tmp._ && tmp._['#']){ // convert from old format
- return setTimeout.each(Object.keys(tmp).sort(), function(k){
+ return setTimeout.each(Object.keys(tmp).sort(), function(k){ // TODO: .keys( is slow
if('_' == k || !(state = state_is(tmp, k))){ return }
cat.on('in', {put: {'#': tmp._['#'], '.': k, ':': tmp[k], '>': state}});
});
@@ -648,10 +648,10 @@
} else {}
eve.to.next(msg); // 1st API job is to call all the listeners.
- setTimeout.each(Object.keys(cat.act||''), function(act){ // 1st API job is to call all chain listeners.
+ setTimeout.each(Object.keys(cat.act||''), function(act){ // 1st API job is to call all chain listeners. // TODO: .keys( is slow
(act = cat.act[act]) && act(msg);
},0,99);
- setTimeout.each(Object.keys(cat.echo||''), function(lat){ // & linked chains
+ setTimeout.each(Object.keys(cat.echo||''), function(lat){ // & linked chains // TODO: .keys( is slow
if(!(lat = cat.echo[lat])){ return }
lat.on('in', msg);
},0,99);
@@ -659,7 +659,7 @@
if(u === change){ // 1st edge case: If we have a brand new database, no data will be found.
cat.put = u; // empty out the cache if, for example, alice's car's color no longer exists (relative to alice) if alice no longer has a car.
delete cat.link; // TODO: Empty out links, maps, echos, acks/asks, etc.?
- setTimeout.each(Object.keys(cat.next||''), function(get, sat){ // empty out all sub properties.
+ setTimeout.each(Object.keys(cat.next||''), function(get, sat){ // empty out all sub properties. // TODO: .keys( is slow
if(!(sat = cat.next[get])){ return }
sat.on('in', {get: get, put: u, $: sat.$});
},0,99);
@@ -679,7 +679,7 @@
if((tmp = cat.ask||'')['']){
sat.on('out', {get: {'#': link}});
} else {
- setTimeout.each(Object.keys(tmp), function(get, sat){ // if sub chains are asking for data.
+ setTimeout.each(Object.keys(tmp), function(get, sat){ // if sub chains are asking for data. // TODO: .keys( is slow
if(!(sat = cat.ask[get])){ return }
sat.on('out', {get: {'#': link, '.': get}}); // go get it.
},0,99);
@@ -781,7 +781,7 @@
if(cat.jam){ return cat.jam.push([cb, as]) }
cat.jam = [[cb,as]];
gun.get(function go(msg, eve){
- if(u === msg.put && !cat.root.opt.super && (tmp = Object.keys(cat.root.opt.peers).length) && ++acks <= tmp){ // TODO: super should not be in core code, bring AXE up into core instead to fix?
+ if(u === msg.put && !cat.root.opt.super && (tmp = Object.keys(cat.root.opt.peers).length) && ++acks <= tmp){ // TODO: super should not be in core code, bring AXE up into core instead to fix? // TODO: .keys( is slow
return;
}
eve.rid(msg);
@@ -878,7 +878,7 @@
}
if(k && v){ at.node = state_ify(at.node, k, s, d) } // handle soul later.
else {
- as.seen.push(cat = {it: d, link: {}, todo: g? [] : Object.keys(d).sort().reverse()});
+ as.seen.push(cat = {it: d, link: {}, todo: g? [] : Object.keys(d).sort().reverse()}); // Any perf reasons to CPU schedule this .keys( ?
at.node = state_ify(at.node, k, s, cat.link);
!g && to.push(cat);
// ---------------
@@ -922,7 +922,7 @@
}, as.opt), acks = 0, stun = as.stun;
if((tmp = cat.root.stun) && --tmp._ === 0){ delete cat.root.stun }
(tmp = function(){ // this is not official yet, but quick solution to hack in for now.
- setTimeout.each(Object.keys(stun||''), function(cb){if(cb = stun[cb]){cb()}});
+ setTimeout.each(Object.keys(stun||''), function(cb){if(cb = stun[cb]){cb()}}); // Any perf reasons to CPU schedule this .keys( ?
}).hatch = tmp; // this is not official yet ^
(as.via._).on('out', {put: as.out = as.graph, opt: as.opt, '#': ask, _: tmp});
}
@@ -1023,29 +1023,29 @@
at.ack = 0; // so can resubscribe.
if(tmp = cat.next){
if(tmp[at.get]){
- obj_del(tmp, at.get);
+ delete tmp[at.get];
} else {
}
}
if(tmp = cat.ask){
- obj_del(tmp, at.get);
+ delete tmp[at.get];
}
if(tmp = cat.put){
- obj_del(tmp, at.get);
+ delete tmp[at.get];
}
if(tmp = at.soul){
- obj_del(cat.root.graph, tmp);
+ delete cat.root.graph[tmp];
}
if(tmp = at.map){
- obj_map(tmp, function(at){
+ Object.keys(tmp).forEach(function(i,at){ at = tmp[i]; //obj_map(tmp, function(at){
if(at.link){
cat.root.$.get(at.link).off();
}
});
}
if(tmp = at.next){
- obj_map(tmp, function(neat){
+ Object.keys(tmp).forEach(function(i,neat){ neat = tmp[i]; //obj_map(tmp, function(neat){
neat.$.off();
});
}
@@ -1228,7 +1228,7 @@
if(!peer && mesh.way){ return mesh.way(msg) }
if(!peer || !peer.id){
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 || {}); // TODO: .keys( is slow
;(function go(){
var S = +new Date;
//Type.obj.map(peer || opt.peers, each); // in case peer is a peer list.
@@ -1390,7 +1390,7 @@
root.on('hi', function(peer, tmp){ this.to.next(peer);
if(!(tmp = peer.url) || !gets[tmp]){ return } delete gets[tmp];
if(opt.super){ return } // temporary (?) until we have better fix/solution?
- setTimeout.each(Object.keys(root.next), function(soul){ var node = root.next[soul];
+ setTimeout.each(Object.keys(root.next), function(soul){ var node = root.next[soul]; // TODO: .keys( is slow
tmp = {}; tmp[soul] = root.graph[soul]; tmp = String.hash(tmp); // TODO: BUG! This is broken.
mesh.say({'##': tmp, get: {'#': soul}}, peer);
});
diff --git a/lib/evict.js b/lib/evict.js
index a4c144c0..7d6ff269 100644
--- a/lib/evict.js
+++ b/lib/evict.js
@@ -25,11 +25,10 @@
var S = +new Date;
var souls = Object.keys(root.graph||empty);
var toss = Math.ceil(souls.length * 0.01);
- //var S = +new Date;
- Gun.list.map(souls, function(soul){
- if(--toss < 0){ return }
+ setTimeout.each(souls, function(soul){
+ if(--toss < 0){ return 1 }
root.$.get(soul).off();
- });
+ },0,99);
root.dup.drop(1000 * 9); // clean up message tracker
console.STAT && console.STAT(S, +new Date - S, 'evict');
}
diff --git a/lib/stats.js b/lib/stats.js
index 0f87d53e..c83dcdf8 100644
--- a/lib/stats.js
+++ b/lib/stats.js
@@ -41,9 +41,9 @@ Gun.on('opt', function(root){
stats.cpu = process.cpuUsage() || {};
stats.cpu.loadavg = os.loadavg();
stats.peers = {};
- stats.peers.count = Object.keys(root.opt.peers||{}).length;
+ stats.peers.count = Object.keys(root.opt.peers||{}).length; // TODO: .keys( is slow
stats.node = {};
- stats.node.count = Object.keys(root.graph||{}).length;
+ stats.node.count = Object.keys(root.graph||{}).length; // TODO: .keys( is slow
stats.all = all;
var dam = root.opt.mesh;
if(dam){
@@ -58,16 +58,18 @@ Gun.on('opt', function(root){
}
console.STAT && console.STAT(S, +new Date - S, 'stats');
S = +new Date;
- fs.writeFile(__dirname+'/../stats.'+root.opt.file, JSON.stringify(stats, null, 2), function(err){ console.STAT && console.STAT(S, +new Date - S, 'stats stash') });
+ JSON.stringifyAsync(stats, function(err, raw){ if(err){ return }
+ fs.writeFile(__dirname+'/../stats.'+root.opt.file, raw, function(err){ console.STAT && console.STAT(S, +new Date - S, 'stats stash') });
+ });
stats.over = S;
stats.gap = {};
exec("top -b -n 1", function(err, out){ out && fs.writeFile(__dirname+'/../stats.top.'+root.opt.file, out, noop) });
}, 1000 * 15);
- Object.keys = Object.keys || function(o){ return Gun.obj.map(o, function(v,k,t){t(k)}) }
});
var exec = require("child_process").exec, noop = function(){};
+require('./yson');
var log = Gun.log, all = {}, max = 1000;
Gun.log = console.STAT = function(a,b,c,d){
diff --git a/lib/store.js b/lib/store.js
index 58102b68..0e990209 100644
--- a/lib/store.js
+++ b/lib/store.js
@@ -4,7 +4,7 @@ Gun.on('create', function(root){
if(Gun.TESTING){ root.opt.file = 'radatatest' }
this.to.next(root);
var opt = root.opt, empty = {}, u;
- if(false === opt.radisk){ return }
+ if(false === opt.rad || false === opt.radisk){ return }
var Radisk = (Gun.window && Gun.window.Radisk) || require('./radisk');
var Radix = Radisk.Radix;
var dare = Radisk(opt), esc = String.fromCharCode(27);
diff --git a/nts.js b/nts.js
index c0ee6b5b..63788fe3 100644
--- a/nts.js
+++ b/nts.js
@@ -1,49 +1,40 @@
;(function(){
- // NOTE: While the algorithm is P2P,
- // the current implementation is one sided,
- // only browsers self-modify, servers do not.
- // Need to fix this! Since WebRTC is now working.
- var env;
- if(typeof global !== "undefined"){ env = global }
- if(typeof window !== "undefined"){ var Gun = (env = window).Gun }
- else {
- if(typeof require !== "undefined"){ var Gun = require('./gun') }
- }
+ var Gun = (typeof window !== "undefined")? window.Gun : require('./gun');
- Gun.on('opt', function(ctx){
- this.to.next(ctx);
- if(ctx.once){ return }
- ctx.on('in', function(at){
- if(!at.nts && !at.NTS){
- return this.to.next(at);
- }
- if(at['@']){
- (ask[at['@']]||noop)(at);
+ Gun.on('create', function(root){ // switch to DAM, deprecated old
+ var opt = root.opt, mesh = opt.mesh;
+ if(!mesh){ return }
+ var asks = {};
+ mesh.hear['nts'] = function(msg, peer){
+ if(msg.nts){
+ (asks[msg['@']]||noop)(msg);
return;
}
- if(env.window){
- return this.to.next(at);
- }
- this.to.next({'@': at['#'], nts: Gun.time.is()});
+ mesh.say({dam: 'nts', nts: Gun.state(), '@': msg['#']}, peer);
+ }
+ var peers = 0;
+ root.on('hi', function(peer){ this.to.next(peer);
+ peers++;
+ setTimeout(function ping(){
+ var NTS = {}, ack = String.random(3), msg = {'#': ack, dam: 'nts'};
+ NTS.start = Gun.state();
+ asks[ack] = function(msg){
+ NTS.end = Gun.state();
+ delete asks[ack];
+ NTS.latency = (NTS.end - NTS.start)/2;
+ if(!msg.nts){ return }
+ NTS.calc = NTS.latency + msg.nts;
+ NTS.step = (NTS.end - NTS.calc)/2;
+ Gun.state.drift -= NTS.step * (1/(peers||1));
+ NTS.next = Math.min(2e4, Math.max(250, 150000 / Math.abs((NTS.end - NTS.calc)||1)));
+ console.log("I am now", Gun.state(), "they are", NTS.calc, "time sync in", NTS.next/1000, 'sec.');
+ setTimeout(ping, NTS.next); // Thanks @finwo ! https://discord.com/channels/612645357850984470/612645357850984473/755334349699809300
+ }
+ mesh.say(msg, peer);
+ }, 1);
});
- var ask = {}, noop = function(){};
- if(!env.window){ return }
-
- Gun.state.drift = Gun.state.drift || 0;
- setTimeout(function ping(){
- var NTS = {}, ack = Gun.text.random(), msg = {'#': ack, nts: true};
- NTS.start = Gun.state();
- ask[ack] = function(at){
- NTS.end = Gun.state();
- Gun.obj.del(ask, ack);
- NTS.latency = (NTS.end - NTS.start)/2;
- if(!at.nts && !at.NTS){ return }
- NTS.calc = NTS.latency + (at.NTS || at.nts);
- Gun.state.drift -= (NTS.end - NTS.calc)/2;
- setTimeout(ping, 1000);
- }
- ctx.on('out', msg);
- }, 1);
+ root.on('bye', function(peer){ --peers; this.to.next(peer) });
});
+
// test by opening up examples/game/nts.html on devices that aren't NTP synced.
}());
\ No newline at end of file