mirror of
https://github.com/amark/gun.git
synced 2025-10-14 00:59:35 +00:00
path bug fixes & NTS
This commit is contained in:
parent
0239023e92
commit
2c80ae81e9
34
gun.js
34
gun.js
@ -132,7 +132,7 @@
|
||||
Gun.is.graph(graph, function(node, ss){
|
||||
c += 1; s = ss;
|
||||
Gun.HAM(vertex, node, function(){}, function(vertex, field, value){
|
||||
(vertex._[Gun._.HAM] = vertex._[Gun._.HAM] || {})[field] = node._[Gun._.HAM][field];
|
||||
(vertex._[Gun._.HAM] = vertex._[Gun._.HAM] || {})[field] = (node._[Gun._.HAM] = node._[Gun._.HAM] || {})[field];
|
||||
vertex[field] = value;
|
||||
}, function(){});
|
||||
});
|
||||
@ -489,7 +489,6 @@
|
||||
var chain = this || gun, src = opt.src || gun;
|
||||
var ctx = {path: path.split('.')}, field = Gun.text.ify(ctx.path.shift());
|
||||
var val = node[field], soul = Gun.is.soul(val);
|
||||
console.log("chain.path", field, node, '\n');
|
||||
if(!field && !ctx.path.length){
|
||||
cb.call(chain, null, node, field);
|
||||
return opt.step? src._.at('soul').emit({soul: $.soul, field: null, from: opt.step.soul, at: opt.step.field, gun: chain, PATH: 'SOUL'})
|
||||
@ -497,10 +496,9 @@
|
||||
}
|
||||
if(!Gun.obj.has(node, field)){
|
||||
if(opt.end || (!ctx.path.length && gun.__.meta($.soul).end)){ // TODO: Make it so you can adjust how many terminations!
|
||||
console.log("whap!");
|
||||
// TODO: BUG! `chain` here is incorrect on unknowns.
|
||||
// TODO: BUG! `chain` here is incorrect on unknowns. This has been fixed at an API level.
|
||||
cb.call(chain, null, null, field);
|
||||
src._.at('soul').emit({soul: $.soul, field: field, gun: chain, PATH: 'SOUL'});
|
||||
src._.at('null').emit({soul: $.soul, field: field, gun: chain, PATH: 'NULL'});
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -590,18 +588,18 @@
|
||||
If this causes any application-level concern, it can compare against the live data by immediately reading it, or accessing the logs if enabled.
|
||||
*/
|
||||
Chain.put = function(val, cb, opt){ // TODO: handle case where val is a gun context!
|
||||
var gun = this.chain(), call = function(){
|
||||
gun.back._.at('soul').emit({soul: Gun.is.soul.on(val) || Gun.roulette.call(gun), empty: true, PUT: 'SOUL'}); // TODO: refactor Gun.roulette!
|
||||
var gun = this.chain(), call = function($){
|
||||
gun.back._.at('soul').emit({soul: $.soul || Gun.is.soul.on(val) || Gun.roulette.call(gun), field: $.field, empty: true, gun: $.gun, PUT: 'SOUL'}); // TODO: refactor Gun.roulette!
|
||||
}, drift = Gun.time.now(); // TODO: every instance of gun maybe should have their own version of time.
|
||||
cb = cb || function(){};
|
||||
opt = opt || {};
|
||||
if(!gun.back.back){
|
||||
gun = gun.chain();
|
||||
call();
|
||||
call({});
|
||||
}
|
||||
if(gun.back.not){ gun.back.not(call) }
|
||||
if(gun.back.not){ gun.back.not(call, {raw: true}) }
|
||||
|
||||
gun.back._.at('soul').event(function($){ // TODO: maybe once per soul?
|
||||
gun.back._.at('soul').once(function($){ // TODO: maybe once per soul?
|
||||
var chain = $.gun || gun;
|
||||
var ctx = {}, obj = val, $ = Gun.obj.copy($);
|
||||
console.log("chain.put", val, '\n');
|
||||
@ -644,7 +642,7 @@
|
||||
env.graph[at.node._[Gun._.soul] = at.soul] = at.node;
|
||||
cb(at, at.soul);
|
||||
};
|
||||
$.empty? path() : gun.back.path(at.path, path, {once: true, end: true}); // TODO: clean this up.
|
||||
($.empty && !$.field)? path() : chain.back.path(at.path, path, {once: true, end: true}); // TODO: clean this up.
|
||||
}
|
||||
}
|
||||
if(!at.node._[Gun._.HAM]){
|
||||
@ -671,6 +669,7 @@
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return gun;
|
||||
}
|
||||
Chain.map = function(cb, opt){
|
||||
@ -711,19 +710,22 @@
|
||||
obj[index] = val;
|
||||
return Gun.is.value(val)? gun.put(obj, cb) : gun.put(obj, cb).path(index);
|
||||
}
|
||||
Chain.not = function(cb){
|
||||
Chain.not = function(cb, opt){
|
||||
var gun = this, ctx = {};
|
||||
cb = cb || function(){};
|
||||
opt = opt || {};
|
||||
|
||||
gun._.at('null').once(function(key){
|
||||
if(key.soul || gun.__.key.s[key = (key || {}).key]){ return }
|
||||
gun._.at('null').once(function($){
|
||||
if($.key && ($.soul || gun.__.key.s[$.key])){ return }
|
||||
if($.field && Gun.obj.has(gun.__.graph[$.soul], $.field)){ return }
|
||||
// TODO! BUG? Removed a start flag check and tests passed, but is that an edge case?
|
||||
var kick = function(next){
|
||||
if(++c){ return Gun.log("Warning! Multiple `not` resumes!"); }
|
||||
next._.at('soul').once(function($){ $.N0T = 'KICK SOUL'; gun._.at('soul').emit($) });
|
||||
}, chain = gun.chain(), next = cb.call(chain, key, kick), c = -1;
|
||||
}, chain = gun.chain(), next = cb.call(chain, opt.raw? $ : ($.field || $.key), kick), c = -1;
|
||||
if(Gun.is(next)){ kick(next) }
|
||||
chain._.at('soul').emit({soul: Gun.roulette.call(chain), empty: true, key: key, N0T: 'SOUL', WAS: 'ON'}); // WAS ON! TOOD: refactor Gun.roulette
|
||||
gun.__.graph[kick.soul = Gun.roulette.call(chain)] = gun.__.graph[kick.soul] || Gun.union.pseudo(kick.soul); // TODO: refactor Gun.roulette
|
||||
chain._.at('soul').emit({soul: kick.soul, empty: true, key: $.key, field: $.field, N0T: 'SOUL', WAS: 'ON'}); // WAS ON!
|
||||
});
|
||||
|
||||
return gun;
|
||||
|
38
lib/nts.js
38
lib/nts.js
@ -1,23 +1,23 @@
|
||||
Gun.on('opt').event(function(gun, opt){
|
||||
if(!Gun.request){ return }
|
||||
var objectiveTimeOffset = 0;
|
||||
Gun.obj.map(opt.peers || gun.__.opt.peers, function(peer, url){
|
||||
var NTS = {};
|
||||
NTS.start = Gun.time.is();
|
||||
console.log(url + '.nts');
|
||||
Gun.request(url + '.nts', null, function(err, reply){
|
||||
console.log("reply", err, reply);
|
||||
if(err || !reply || !reply.body){
|
||||
return console.log("Network Time Synchronization not supported", err, (reply || {}).body);
|
||||
}
|
||||
NTS.end = Gun.time.is();
|
||||
NTS.latency = (NTS.end - NTS.start)/2;
|
||||
if(Gun.obj.has(reply.body, 'time')){ return }
|
||||
NTS.calc = reply.body.time + NTS.latency;
|
||||
objectiveTimeOffset += (objectiveTimeOffset - NTS.calc)/2;
|
||||
console.log('NTS', NTS.latency, NTS.calc, objectiveTimeOffset);
|
||||
}, {});
|
||||
});
|
||||
if(!gun.tab || !gun.tab.request){ return }
|
||||
Gun.time.now.drift = 0;
|
||||
function ping(){
|
||||
Gun.obj.map(opt.peers || gun.__.opt.peers, function(peer, url){
|
||||
var NTS = {};
|
||||
NTS.start = Gun.time.now();
|
||||
gun.tab.request(url, null, function(err, reply){
|
||||
if(err || !reply || !reply.body){
|
||||
return console.log("Network Time Synchronization not supported", err, (reply || {}).body);
|
||||
}
|
||||
NTS.end = Gun.time.now();
|
||||
NTS.latency = (NTS.end - NTS.start)/2;
|
||||
if(!Gun.obj.has(reply.body, 'time')){ return }
|
||||
NTS.calc = NTS.latency + reply.body.time;
|
||||
Gun.time.now.drift -= (NTS.end - NTS.calc)/2;
|
||||
setTimeout(ping, 250);
|
||||
}, {url: {pathname: '.nts'}});
|
||||
});
|
||||
}; ping();
|
||||
});
|
||||
// You need to figure out how to make me write tests for this!
|
||||
// maybe we can do human based testing where we load a HTML that just
|
||||
|
31
lib/wsp.js
31
lib/wsp.js
@ -102,12 +102,11 @@
|
||||
var key = req.url.key
|
||||
, reply = {headers: {'Content-Type': tran.json}};
|
||||
//console.log(req);
|
||||
/* NTS HACK! SHOULD BE ITS OWN ISOLATED MODULE!
|
||||
/* NTS HACK! SHOULD BE ITS OWN ISOLATED MODULE! */
|
||||
if(req && req.url && req.url.pathname && req.url.pathname.indexOf('gun.nts') >= 0){
|
||||
console.log("GOT IT");
|
||||
return cb({headers: reply.headers, body: {time: Gun.time.is() }});
|
||||
}
|
||||
NTS END! SHOULD HAVE BEEN ITS OWN MODULE */
|
||||
/* NTS END! SHOULD HAVE BEEN ITS OWN MODULE */
|
||||
if(req && req.url && Gun.obj.has(req.url.query, '*')){
|
||||
return gun.all(req.url.key + req.url.search, function(err, list){
|
||||
cb({headers: reply.headers, body: (err? (err.err? err : {err: err || "Unknown error."}) : list || null ) })
|
||||
@ -161,32 +160,6 @@
|
||||
});
|
||||
}).err){ cb({headers: reply.headers, body: {err: req.err || "Union failed."}}) }
|
||||
}
|
||||
|
||||
return;
|
||||
//return;
|
||||
// saving
|
||||
Gun.obj.map(req.body, function(node, soul){ // iterate over every node
|
||||
if(soul != Gun.is.soul.on(node)){ return this.end("No soul!") }
|
||||
gun.get({'#': soul}, this.add(soul)); // and begin getting it in case it is not cached.
|
||||
}, Gun.fns.sum(function(err){
|
||||
if(err){ return reply.err = err }
|
||||
reply.got = true;
|
||||
}));
|
||||
// could there be a timing error somewhere in here?
|
||||
var setImmediate = setImmediate || setTimeout; // TODO: BUG: This should be cleaned up, but I want Heroku to work.
|
||||
setImmediate(function(){ // do not do it right away because gun.get above is async, this should be cleaner.
|
||||
var context = Gun.union(gun, req.body, function check(err, ctx){ // check if the body is valid, and get it into cache immediately.
|
||||
context = ctx || context;
|
||||
if(err || reply.err || context.err || !context.nodes){ return cb({headers: reply.headers, body: {err: err || reply.err || context.err || "Union failed." }}) }
|
||||
if(!Gun.fns.is(gun.__.opt.hooks.put)){ return cb({headers: reply.headers, body: {err: "Persistence not supported." }}) }
|
||||
if(!reply.got){ return setTimeout(check, 2) } // only persist if all nodes are in cache.
|
||||
gun.__.opt.hooks.put(context.nodes, function(err, data){ // since we've already manually done the union, we can now directly call the persistence layer.
|
||||
if(err){ return cb({headers: reply.headers, body: {err: err || "Persistence failed." }}) }
|
||||
cb({headers: reply.headers, body: {ok: "Persisted."}}); // TODO: Fix so we know what the reply is.
|
||||
});
|
||||
});
|
||||
}, 0);
|
||||
gun.server.on('network').emit(req);
|
||||
}
|
||||
tran.put.key = function(req, cb){ // key hook!
|
||||
if(!req || !req.url || !req.url.key || !Gun.obj.has(req.body, Gun._.soul)){ return }
|
||||
|
102
test/common.js
102
test/common.js
@ -9,8 +9,9 @@ describe('Gun', function(){
|
||||
var t = {};
|
||||
|
||||
describe('Utility', function(){
|
||||
|
||||
it('verbose console.log debugging', function(done) { console.log("TURN THIS BACK ON the DEBUGGING TEST"); done(); return;
|
||||
|
||||
/* // causes logger to no longer log.
|
||||
it('verbose console.log debugging', function(done) {
|
||||
|
||||
var gun = Gun();
|
||||
var log = root.console.log, counter = 1;
|
||||
@ -31,6 +32,7 @@ describe('Gun', function(){
|
||||
});
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
describe('Type Check', function(){
|
||||
it('binary', function(){
|
||||
@ -1408,7 +1410,7 @@ describe('Gun', function(){
|
||||
|
||||
});
|
||||
|
||||
it('val path put val key', function(done){ // bug discovered from Jose's visualizer // TODO: still timing issues, 0.6!
|
||||
it('val path put val key', function(done){ // bug discovered from Jose's visualizer
|
||||
var gun = Gun(), s = Gun.time.is(), n = function(){ return Gun.time.is() }
|
||||
this.timeout(5000);
|
||||
|
||||
@ -1417,8 +1419,8 @@ describe('Gun', function(){
|
||||
gun.get('user/alfred').val(function(a){
|
||||
gun.get('user/beth').path('friend').put(a); // b - friend_of -> a
|
||||
gun.get('user/beth').val(function(b){ // TODO: We should have b.friend by now!
|
||||
gun.get('user/alfred').path('friend').put(b, function(){ // a - friend_of -> b
|
||||
gun.get('user/beth').path('cat').put({name: "fluffy", age: 3, coat: "tabby"}, function(err, ok){
|
||||
gun.get('user/alfred').path('friend').put(b).val(function(beth){ // a - friend_of -> b
|
||||
gun.get('user/beth').path('cat').put({name: "fluffy", age: 3, coat: "tabby"}).val(function(cat){
|
||||
|
||||
gun.get('user/alfred').path('friend.cat').key('the/cat');
|
||||
|
||||
@ -1837,36 +1839,26 @@ describe('Gun', function(){
|
||||
})
|
||||
});
|
||||
|
||||
it.skip("gun get empty set, path val -> this put", function(done){ // Issue #99 #101, bug in survey and trace game.
|
||||
it("gun get empty set, path not -> this put", function(done){ // Issue #99 #101, bug in survey and trace game.
|
||||
var test = {c: 0}, u;
|
||||
var gun = Gun();
|
||||
console.log("game = gun get GAME set");
|
||||
var game = gun.get('some/not/yet/set/put/thing').set();
|
||||
console.log("me = game data path ALIAS val");
|
||||
// TODO: add one for NOT
|
||||
// the behavior we decided is VAL will hang until data defined
|
||||
// NOT will get called after first peer (or configurable).
|
||||
var me = game.path('alias').on(function(val){
|
||||
console.log("TESTING!!!!", val);
|
||||
var me = game.path('alias').val(function(val){
|
||||
expect(val).to.not.be(u);
|
||||
expect(val.a).to.be('b');
|
||||
var meid = Gun.is.soul.on(val);
|
||||
var self = this;
|
||||
expect(self === game).to.not.be.ok();
|
||||
expect(self === me).to.be.ok();
|
||||
if(test.c++){ return }
|
||||
self.put({x: 0, y: 0});
|
||||
setTimeout(function(){
|
||||
var graph = Gun.obj.copy(game.__.graph);
|
||||
Gun.obj.map(graph, function(node){delete node._});
|
||||
|
||||
},100);
|
||||
})
|
||||
done();
|
||||
});
|
||||
setTimeout(function(){
|
||||
me.put({a: 'b'});
|
||||
});
|
||||
});
|
||||
|
||||
// gr.put({a: {b: {c: 'd'}}}).path('z').set().val(); TEST sets on paths.
|
||||
|
||||
it.skip("gun get empty set path empty later path put multi", function(done){ // Issue #99 #101, bug in survey and trace game.
|
||||
Gun.log.verbose = true;
|
||||
it("gun get empty set path empty later path put multi", function(done){ // Issue #99 #101, bug in survey and trace game.
|
||||
done.c = 0;
|
||||
var gun = Gun();
|
||||
var data = gun.get('some/not/yet/set/put/thing/2').set();
|
||||
var path = data.path('sub');
|
||||
@ -1874,23 +1866,15 @@ describe('Gun', function(){
|
||||
setTimeout(function(){
|
||||
path.put(d, function(err, ok){
|
||||
expect(err).to.not.be.ok();
|
||||
if(f){
|
||||
path.val(function(v){
|
||||
delete v._;
|
||||
expect(v).to.eql(d);
|
||||
done();
|
||||
});
|
||||
done.c++;
|
||||
if(f && done.c >= 3){
|
||||
done();
|
||||
}
|
||||
});
|
||||
setTimeout(function(){
|
||||
data.val(function(v){
|
||||
console.log(d, "DATA", data.__.graph);
|
||||
});
|
||||
},2)
|
||||
},t || 10);
|
||||
};
|
||||
put({on: 'bus', not: 'transparent'});
|
||||
put({on: null, not: 'torrent'}, 100);
|
||||
put({on: null, not: 'torrent'}, 200);
|
||||
put({on: 'sub', not: 'parent'}, 250, true);
|
||||
});
|
||||
|
||||
@ -1943,8 +1927,8 @@ describe('Gun', function(){
|
||||
done.c = 0;
|
||||
var u;
|
||||
var gun = Gun();
|
||||
var game = gun.get('players').set();
|
||||
var me = game.path('player3').val(function(val){
|
||||
var game = gun.get('game1/players').set();
|
||||
var me = game.path('player1').val(function(val){
|
||||
if(!done.c){ done.fail = true }
|
||||
expect(val).to.not.be(u);
|
||||
expect(val.x).to.be(0);
|
||||
@ -1956,35 +1940,51 @@ describe('Gun', function(){
|
||||
done.c++;
|
||||
expect(done.fail).to.not.be.ok();
|
||||
me.put({x: 0, y: 0});
|
||||
},10)
|
||||
},10);
|
||||
});
|
||||
|
||||
it.only("gun get path empty on", function(done){
|
||||
it("gun get path empty on", function(done){
|
||||
done.c = 0;
|
||||
var u;
|
||||
var gun = Gun();
|
||||
var game = gun.get('players').set();
|
||||
var me = game.path('player3').on(function(val){
|
||||
var game = gun.get('game2/players').set();
|
||||
var me = game.path('player2').on(function(val){
|
||||
if(!done.c){ done.fail = true }
|
||||
expect(val).to.not.be(u);
|
||||
expect(val.x).to.be(0);
|
||||
expect(val.y).to.be(0);
|
||||
expect(val.x).to.be(1);
|
||||
expect(val.y).to.be(1);
|
||||
expect(done.fail).to.not.be.ok();
|
||||
if(done.c > 1){ return } // it is okay if ON gets called many times, this protects against that.
|
||||
// although it would be nice if we could minimize the amount of duplications.
|
||||
done();
|
||||
done.c++;
|
||||
});
|
||||
setTimeout(function(){
|
||||
done.c++;
|
||||
expect(done.fail).to.not.be.ok();
|
||||
me.put({x: 0, y: 0});
|
||||
},10)
|
||||
me.put({x: 1, y: 1});
|
||||
},10);
|
||||
});
|
||||
|
||||
it.skip("gun get path empty not", function(done){
|
||||
var g = Gun();
|
||||
it("gun get path empty not", function(done){
|
||||
var u;
|
||||
var gun = Gun();
|
||||
var game = gun.get('game3/players').set();
|
||||
var me = game.path('player3').not(function(field){
|
||||
expect(field).to.be('player3');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it.skip("gun get path empty set", function(done){
|
||||
var g = Gun();
|
||||
it("gun get path empty set", function(done){
|
||||
var u;
|
||||
var gun = Gun();
|
||||
var game = gun.get('game4/players').set();
|
||||
var me = game.path('player4').set().path('alias').put('awesome').val(function(val, field){
|
||||
expect(val).to.be('awesome');
|
||||
expect(field).to.be('alias');
|
||||
done();
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user