mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
Before adding queue to on
This commit is contained in:
parent
ac761bf674
commit
752fe41a19
159
gun.js
159
gun.js
@ -176,7 +176,8 @@
|
||||
function noop(){};
|
||||
function Event(tag, arg, at, as, skip){
|
||||
var ctx = this, ons = ctx.ons || (ctx.ons = {}), on = ons[tag] || (ons[tag] = {s: []}), act, mem;
|
||||
/*if(!arg && 1 === arguments.length){
|
||||
//typeof console !== 'undefined' && console.debug(102, 'on', tag, arg, 'ons', ctx, ons);
|
||||
/*if(!arg && 1 === arguments.length){ // Performance drops significantly even though `arguments.length` should be okay to use.
|
||||
return on.s;
|
||||
}*/
|
||||
if(arg instanceof Function){
|
||||
@ -188,7 +189,7 @@
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
return;
|
||||
return act;
|
||||
}
|
||||
if(emit){ emit(tag, arg, on, ctx) }
|
||||
on.arg = arg;
|
||||
@ -226,9 +227,9 @@
|
||||
}
|
||||
}
|
||||
on.s = still;
|
||||
if(0 === still.length){
|
||||
delete ons[tag];
|
||||
}
|
||||
//if(0 === still.length){ // TODO: BUG! If we clean up the events themselves when no longer needed by deleting this code, it causes some tests to fail.
|
||||
// delete ons[tag];
|
||||
//}
|
||||
}
|
||||
if(!gap && at && at instanceof Function){
|
||||
at.call(as, arg);
|
||||
@ -237,7 +238,9 @@
|
||||
}
|
||||
exports.on = Event;
|
||||
}(Util, function add(tag, act, on, ctx){ // Gun specific extensions
|
||||
var mem = on.mem, at;
|
||||
var mem = on.mem;
|
||||
typeof console !== 'undefined' && console.debug(9, 'ON', tag, mem);
|
||||
typeof console !== 'undefined' && console.debug(10, 'SO! The problem is that subsequent event listeners trigger lazy again, but the should queue for the results of the one already trying to finish or else you will get wrong results.');
|
||||
if(mem){
|
||||
if(mem instanceof Array){
|
||||
act.fn.apply(act.at, mem.concat(act));
|
||||
@ -246,11 +249,10 @@
|
||||
}
|
||||
return;
|
||||
}
|
||||
at = act.at? act.at.gun? act.at : ctx : ctx;
|
||||
if(!at.lex || !at.lex.soul){ return } // TODO: What about lex cursors?
|
||||
console.debug(16, 'on', tag, mem);
|
||||
console.debug(3, 'on', tag, mem);
|
||||
Gun.get(at);
|
||||
if(!ctx.lazy){ return }
|
||||
var at = act.at? act.at.gun? act.at : ctx : ctx;
|
||||
if(!at.gun){ return }
|
||||
ctx.lazy(at, tag);
|
||||
//if(on.mem){ add(tag, act, on, ctx) } // for synchronous async actions.
|
||||
}, function(tag, arg, on, at){
|
||||
on.mem = arg;
|
||||
@ -606,8 +608,7 @@
|
||||
is_graph(at.graph, map, null, at);
|
||||
});
|
||||
function map(node, soul){
|
||||
console.debug(12, 'put to get', soul);
|
||||
console.debug(9, 'put to get', soul);
|
||||
//Gun.get.got.call(this, null, node);
|
||||
Gun.get.got.call(this.gun.__.gun.get(soul)._, null, node);
|
||||
}
|
||||
}());
|
||||
@ -626,20 +627,21 @@
|
||||
stream: cb
|
||||
}
|
||||
}
|
||||
console.debug(4, 'GET', at);
|
||||
console.debug(5, 'GET', at.lex);
|
||||
Gun.on('get', at); // TODO: What is the cleanest way to reply if there is no responses, without assuming drivers do reply or not?
|
||||
return at.gun;
|
||||
}
|
||||
Gun.get.got = got;
|
||||
function got(err, node){
|
||||
function got(err, node){ var at = this;
|
||||
if(err){ Gun.log(err) }
|
||||
console.debug(105, 'GOT', err, node);
|
||||
console.debug(5, 'GOT', err, node);
|
||||
Gun.on('stream', Gun.obj.to(this, {err: err, change: node}), stream);
|
||||
if(!at.stream){ var soul;
|
||||
if(!node && !at.lex.soul){ return }
|
||||
at = at.gun.__.gun.get(is_node_soul(node) || at.lex.soul)._;
|
||||
}
|
||||
Gun.on('stream', Gun.obj.to(at, {err: err, change: node}), stream);
|
||||
}
|
||||
function stream(at){
|
||||
if(!at.stream){ console.log("WARNING! No at.get", at); }
|
||||
console.debug(6, 'STREAM', at);
|
||||
if(!at.stream){ console.log("WARNING! No at.stream", at); }
|
||||
at.stream(at.err, at.change);
|
||||
}
|
||||
}());
|
||||
@ -649,6 +651,7 @@
|
||||
if(opt.force){ return }
|
||||
var lex = at.lex, gun = at.gun, graph = gun.__.graph, node = graph[lex.soul];
|
||||
if(opt.memory || node){ return at.cb(null, node), ev.stun() }
|
||||
console.debug(6, 'not in memory');
|
||||
});
|
||||
|
||||
Gun.on('stream', function(at, ev){ var node;
|
||||
@ -667,8 +670,8 @@
|
||||
if(get && get[soul] && !get[soul]._.node){
|
||||
get[soul]._.node = __.graph[soul];
|
||||
}
|
||||
});
|
||||
*/
|
||||
});*/
|
||||
|
||||
Gun.on('stream', function(at){
|
||||
var lex = at.lex, soul = lex.soul, field = lex.field;
|
||||
var gun = at.gun, graph = gun.__.graph, node = graph[soul], u;
|
||||
@ -840,12 +843,13 @@
|
||||
put.any = cb;
|
||||
put.data = data;
|
||||
put.state = (opt.state || opts.state)();
|
||||
console.debug(3, 'put put', data);
|
||||
at.on('chain', link, at); // TODO: ONE?
|
||||
return gun;
|
||||
};
|
||||
function link(cat, ev){ ev.off(); // TODO: BUG!
|
||||
console.log(8, 'putting', cat);
|
||||
var at = this, put = at.put, data, cb;
|
||||
console.debug(7, 'putting', at, cat.gun === at.gun, cat);
|
||||
if(cat.err){ return }
|
||||
if(!cat.node && (put.opt.init || cat.gun.__.opt.init)){ return }
|
||||
// TODO: BUG! `at` doesn't have correct backwards data!
|
||||
@ -858,9 +862,9 @@
|
||||
ev.stun();
|
||||
//put.resume = ev.stun(put.resume);
|
||||
Gun.ify(data, end, {
|
||||
node: function(env, cb){ var eat = env.at;
|
||||
node: function(env, cb){ var eat = env.at, tmp;
|
||||
if(1 === eat.path.length && cat.node){
|
||||
eat.soul = is_rel(cat.node[eat.path[0]]); // TODO: BUG! Need to handle paths that aren't loaded yet.
|
||||
eat.soul = (tmp = is_rel(at.value))? tmp : is_rel(cat.node[eat.path[0]]); // TODO: BUG! Need to handle paths that aren't loaded yet.
|
||||
}
|
||||
cb(env, eat);
|
||||
}, value: function(env){ var eat = env.at;
|
||||
@ -892,11 +896,9 @@
|
||||
Gun.on('normalize', Gun.obj.to(at, {err: err, graph: env.graph, env: env}), wire);
|
||||
}
|
||||
function wire(at){
|
||||
console.debug(8, 'pat', at);
|
||||
Gun.put(Gun.obj.to(at, {cb: ack}));
|
||||
}
|
||||
function ack(err, ok){ var at = this, cb;
|
||||
console.debug(14, 'ack', err, ok);
|
||||
if((cb = at.put.any) && cb instanceof Function){
|
||||
cb.call(at.gun, err, ok);
|
||||
}
|
||||
@ -925,16 +927,23 @@
|
||||
}
|
||||
Gun.on('chain', function(cat, e){
|
||||
if(!is_node_soul(cat.node, 'key')){ return }
|
||||
var resume = e.stun(1), node = cat.node, pseudo = cat.gun._.pseudo || (cat.gun._.pseudo = cat.gun._.node = is_node_ify({}, is_node_soul(node)));
|
||||
var resume = e.stun(1), node = cat.change, field = cat.lex.field, pseudo = cat.gun._.pseudo || (cat.gun._.pseudo = cat.gun._.node = is_node_ify({}, is_node_soul(cat.node)));
|
||||
pseudo._.key = 'pseudo';
|
||||
cat.seen = cat.seen || {}; // TODO: There is a better way.
|
||||
'hello/world' === is_node_soul(node) && console.log("scan", node);
|
||||
is_node(node, function(n, f){ // TODO: PERF! BAD! Filter out items we've already seen.
|
||||
if(cat.seen[f]){ return } cat.seen[f] = true; // TODO: There is a better way.
|
||||
cat.gun.get(Gun.obj.to(cat.lex, {soul: f}), on);
|
||||
function on(err, node){
|
||||
//cat.gun.__.gun.get(Gun.obj.to(cat.lex, {soul: f}), on);
|
||||
if(field){
|
||||
cat.gun.__.gun.get(f).path(field, on);
|
||||
} else {
|
||||
cat.gun.__.gun.get(f, on);
|
||||
}
|
||||
function on(err, node, field, at){
|
||||
if(!node){ return }
|
||||
HAM_node(pseudo, node);
|
||||
cat.node = pseudo;
|
||||
cat.change = at.change;
|
||||
resume();
|
||||
}
|
||||
});
|
||||
@ -966,17 +975,10 @@
|
||||
if(!opt || !opt.path){ var back = this.__.gun; } // TODO: CHANGING API! Remove this line!
|
||||
var gun, back = back || this;
|
||||
var get = back._.get || (back._.get = {}), tmp;
|
||||
console.debug(2, 'get', lex);
|
||||
if(typeof lex === 'string'){
|
||||
if(!(gun = get[lex])){
|
||||
gun = cache(get, lex, back);
|
||||
console.debug(15, 'get', lex, get, 'and the', gun);
|
||||
console.debug(2, 'get', lex);
|
||||
if((tmp = gun._.lex).field){
|
||||
/*if(!back._.ons.chain || !back._.ons.chain.s.length){ // TODO: CLEAN UP! // TODO: ONE?
|
||||
back._.on('chain', link, gun._);
|
||||
}*/
|
||||
back._.on('field:' + tmp.field, field, gun._); // TODO: ONE?
|
||||
}
|
||||
}
|
||||
} else
|
||||
if(!lex && 0 != lex){ // TODO: BUG!?
|
||||
@ -990,7 +992,7 @@
|
||||
if(tmp = lex.soul){
|
||||
if(lex.field){
|
||||
gun = back.chain();
|
||||
gun._.stream = cb;
|
||||
//gun._.stream = cb;
|
||||
gun._.lex = lex;
|
||||
Gun.get(gun._);
|
||||
return gun;
|
||||
@ -1000,59 +1002,82 @@
|
||||
}
|
||||
} else
|
||||
if(tmp = lex[_soul]){
|
||||
if(lex[_field]){
|
||||
return back.get({soul: tmp, field: lex[_field]}, cb, opt);
|
||||
}
|
||||
if(!(gun = get[tmp])){
|
||||
gun = cache(get, tmp, back);
|
||||
}
|
||||
if(tmp = lex[_field]){
|
||||
return gun.path(tmp, cb, opt);
|
||||
}
|
||||
}
|
||||
console.debug(7, 'get', lex);
|
||||
if(cb && cb instanceof Function){
|
||||
gun._.on('any', pop(cb), gun); // TODO: Perf! Batch! // TODO: API CHANGE? Having to use pop is annoying. Should we support NodeJS style callbacks anymore?
|
||||
//gun._.on('any', pop(cb), gun); // TODO: Perf! Batch! // TODO: API CHANGE? Having to use pop is annoying. Should we support NodeJS style callbacks anymore?
|
||||
console.debug(8, 'getting');
|
||||
gun._.on('any', cb, gun); // TODO: Perf! Batch! // TODO: API CHANGE? Having to use pop is annoying. Should we support NodeJS style callbacks anymore?
|
||||
}
|
||||
return gun;
|
||||
}
|
||||
function cache(get, key, back){
|
||||
var gun = get[key] = back.chain(), at = gun._;
|
||||
at.stream = stream;
|
||||
at.lazy = lazy;
|
||||
if(!back.back){
|
||||
at.stream = stream;
|
||||
at.lex.soul = key;
|
||||
} else {
|
||||
var lex = at.lex, flex = back._.lex;
|
||||
var lex = at.lex, cat = back._, flex = cat.lex;
|
||||
lex.field = key;
|
||||
if(!flex.field && flex.soul){
|
||||
lex.soul = flex.soul;
|
||||
}
|
||||
back._.on('field:' + key, field, at);
|
||||
}
|
||||
return gun;
|
||||
}
|
||||
function stream(err, node){
|
||||
console.debug(10, 'stream', err, node);
|
||||
Gun.on('chain', this);
|
||||
//Gun.on('chain', this, link, this);
|
||||
}
|
||||
Gun.on('chain', link);
|
||||
function link(cat, ev){ var at = cat.gun._, u;
|
||||
var err = cat.err, node = cat.node, cex = cat.lex, lex = at.lex, field = lex.field, rel, val;
|
||||
console.debug(13, 'link', at, cat);
|
||||
console.debug(11, 'link', at, cat);
|
||||
if(lex !== cex && lex.field && cex.field){
|
||||
if(obj_has(node, cex.field) && (rel = is_rel(val = node[cex.field]))){
|
||||
return Gun.get(Gun.obj.to(at, {lex: {soul: rel, field: lex.field}}));
|
||||
function lazy(at){ var cat = this;
|
||||
if(at.path && at.path.wait){ return } // means we're being lazy again.
|
||||
console.debug(4, 'lazy', at);
|
||||
var lex = at.lex;
|
||||
if(!lex.soul){
|
||||
if(!(lex.soul = is_rel(cat.value))){
|
||||
return; // TODO: BUG! Handle async case.
|
||||
}
|
||||
}
|
||||
console.debug(17, 'link', at, cat);
|
||||
at.on('any', [err, (field && node)? node[field] : node, field, cat]); // TODO: Revisit!
|
||||
Gun.get(at);
|
||||
};
|
||||
function stream(err, node){
|
||||
//Gun.on('chain', this);
|
||||
Gun.on('chain', this, link, this);
|
||||
}
|
||||
//Gun.on('chain', link);
|
||||
function link(cat, ev){ var at = this, u;
|
||||
//at.value = cat.value = cat.node;
|
||||
var err = cat.err, node = cat.node, cex = cat.lex, lex = at.lex, field = lex.field, rel, val;
|
||||
if(at.path && is_node_soul(node) === at.path.rel){ field = u }
|
||||
at.on('any', [err, (field && node)? node[field] : node, lex.field, cat]) // TODO: Revisit!
|
||||
if(err){ at.on('err', err) }
|
||||
if(node){ at.on('ok', [(field && node)? node[field] : node, field, cat]) } // TODO: Revisit!
|
||||
is_node(at.change, map, {cat: cat, at: at});
|
||||
if(node){ at.on('ok', [(field && node)? node[field] : node, lex.field, cat]) } // TODO: Revisit!
|
||||
at.on('chain', cat);
|
||||
if(at.path && field){ return }
|
||||
is_node(cat.change, map, {cat: cat, at: at}) || obj_map(at.get, map, {cat: cat, at: at}); // TODO: Cleaner way? Necessary to pass error/nots down the chain for implicit puts.
|
||||
}
|
||||
function map(val, field){
|
||||
this.cat.on('field:' + field, this.cat);
|
||||
this.at.on('field:' + field, this.cat);
|
||||
}
|
||||
function field(cat, ev){ var at = this;
|
||||
at.on('chain', Gun.obj.to(at, {err: cat.err, change: cat.change}));
|
||||
var node = cat.node, lex, field, rel;
|
||||
if(!at.path){ at.path = {} }
|
||||
if(!node){ return link.call(at, cat, ev) } // TODO: Errors and nots?
|
||||
(lex = at.lex).soul = is_node_soul(node);
|
||||
if(at.value === node[field = lex.field] && obj_has(at, 'value')){ return }
|
||||
if(at.path.ev){ at.path.ev.off() }
|
||||
at.value = node[field];
|
||||
if(rel = at.path.rel = is_rel(at.value)){
|
||||
at.path.wait = true;
|
||||
at.path.ev = at.gun.__.gun.get(rel)._.on('chain', link, at);
|
||||
at.path.wait = false;
|
||||
return;
|
||||
}
|
||||
link.call(at, cat, ev);
|
||||
}
|
||||
}());
|
||||
Gun.chain.path = function(field, cb, opt){
|
||||
@ -1160,10 +1185,12 @@
|
||||
;(function(){
|
||||
function get(err, data, at){
|
||||
if(!data && !Gun.obj.empty(at.opt.peers)){ return } // let the peers handle no data.
|
||||
console.log("ouch");
|
||||
at.cb(err, data); // node
|
||||
}
|
||||
Gun.on('get', function(at){
|
||||
var opt = at.opt, lex = at.lex;
|
||||
console.debug(7, 'get ASYNC');
|
||||
Tab.store.get((opt.prefix || '') + lex.soul, get, at);
|
||||
});
|
||||
}());
|
||||
@ -1303,10 +1330,10 @@
|
||||
;(function(exports){ var u;
|
||||
function s(){}
|
||||
s.put = function(key, val, cb){ try{ store.setItem(key, Gun.text.ify(val));if(cb)cb(null) }catch(e){if(cb)cb(e)} }
|
||||
s.get = function(key, cb, t){ //setTimeout(function(){
|
||||
s.get = function(key, cb, t){ setTimeout(function(){
|
||||
try{ cb(null, Gun.obj.ify(store.getItem(key) || null), t);
|
||||
}catch(e){ cb(e,u,t)}
|
||||
}//,1) }
|
||||
},1) }
|
||||
s.del = function(key){ return store.removeItem(key) }
|
||||
var store = window.localStorage || {setItem: function(){}, removeItem: function(){}, getItem: function(){}};
|
||||
exports.store = s;
|
||||
|
@ -49,7 +49,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "~>1.9.0",
|
||||
"panic-server": "~>0.2.4",
|
||||
"panic-server": "~>0.3.0",
|
||||
"selenium-webdriver": "~>2.53.2"
|
||||
}
|
||||
}
|
||||
|
@ -1352,9 +1352,11 @@ describe('Gun', function(){
|
||||
});
|
||||
});
|
||||
|
||||
it('put node with soul get soul', function(done){
|
||||
it.only('put node with soul get soul', function(done){
|
||||
Gun.log.debug=1;console.log("--------------------------");
|
||||
gun.put({_: {'#': 'foo'}, hello: 'world'})
|
||||
.get({'#': 'foo'}, function(err, node){
|
||||
console.log("huh?", err, node);
|
||||
expect(err).to.not.be.ok();
|
||||
expect(Gun.is.node.soul(node)).to.be('foo');
|
||||
expect(node.hello).to.be('world');
|
||||
@ -1583,15 +1585,14 @@ describe('Gun', function(){
|
||||
|
||||
it('put node path path', function(done){
|
||||
var gun = Gun();
|
||||
Gun.log.debug=1;console.log("----------------------------------");
|
||||
gun.put({hello: {little: 'world'}}).path('hello').path('little', function(err, val, field){
|
||||
var g = gun.put({hello: {little: 'world'}}).path('hello').path('little', function(err, val, field){
|
||||
if(done.end){ return } // it is okay for path's callback to be called multiple times.
|
||||
expect(err).to.not.be.ok();
|
||||
expect(field).to.be('little');
|
||||
expect(val).to.be('world');
|
||||
done(); done.end = true;
|
||||
});
|
||||
});return;
|
||||
});
|
||||
|
||||
it('put node path rel', function(done){
|
||||
gun.put({foo: {bar: 'lol'}}).path('foo', function(err, val, field){
|
||||
@ -1617,8 +1618,9 @@ describe('Gun', function(){
|
||||
var gun = Gun();
|
||||
gun.put({_:{'#': 'soul/field'}, hi: 'lol', foo: 'bar'});//.key('key/field');
|
||||
gun.get({'#': 'soul/field', '.': 'hi'}, function(err, val){
|
||||
expect(val.hi).to.be('lol');
|
||||
expect(Gun.obj.has(val,'foo')).to.not.be.ok();
|
||||
//expect(val.hi).to.be('lol'); // TODO: REVISE API?
|
||||
expect(val).to.be('lol');
|
||||
//expect(Gun.obj.has(val,'foo')).to.not.be.ok();
|
||||
done();
|
||||
})
|
||||
});
|
||||
@ -1767,7 +1769,7 @@ describe('Gun', function(){
|
||||
expect(val).to.be('are');
|
||||
expect(field).to.be('you');
|
||||
done();
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('get node path put object merge isolated', function(done){
|
||||
@ -1778,6 +1780,8 @@ describe('Gun', function(){
|
||||
var puthi = get.put({hi: 'you'});
|
||||
puthi.on(function(node){
|
||||
if(done.hi){ return }
|
||||
//console.log(1, node);
|
||||
expect(node.hello).to.be('key');
|
||||
expect(node.hi).to.be('you');
|
||||
done.hi = 1;
|
||||
});
|
||||
@ -1787,8 +1791,11 @@ describe('Gun', function(){
|
||||
path2._.id = 'path2';
|
||||
var putyay = path2.put({yay: "value"});
|
||||
putyay.on(function(node, field){
|
||||
if(done.yay){ return }
|
||||
//console.log(2, field, node);
|
||||
expect(field).to.be('hi');
|
||||
expect(node.yay).to.be('value');
|
||||
done.yay = true;
|
||||
});
|
||||
setTimeout(function(){
|
||||
var get3 = gun.get('hello/key/iso');
|
||||
@ -1796,9 +1803,10 @@ describe('Gun', function(){
|
||||
path3._.id = 'path3';
|
||||
var puthappy = path3.put({happy: "faces"});
|
||||
puthappy.on(function(node, field){
|
||||
//console.log(3, field, node);
|
||||
expect(field).to.be('hi');
|
||||
expect(node.yay).to.be('value');
|
||||
expect(node.happy).to.be('faces');
|
||||
expect(node.yay).to.be('value');
|
||||
setTimeout(function(){
|
||||
done();
|
||||
},200);
|
||||
@ -1931,6 +1939,7 @@ describe('Gun', function(){
|
||||
});
|
||||
|
||||
it('get put path', function(done){
|
||||
Gun.log.debug=1;console.log("-------------------------");
|
||||
gun.get('hello/world').put({hello: 'Mark'}).path('hello').val(function(val, field){
|
||||
console.log("WAT?", field, val);
|
||||
expect(val).to.be('Mark');
|
||||
|
@ -1,3 +1,5 @@
|
||||
require('./holy/grail');
|
||||
|
||||
describe('PANIC!', function(){
|
||||
this.timeout(1000 * 100);
|
||||
|
||||
@ -35,7 +37,7 @@ describe('PANIC!', function(){
|
||||
function min(n, done, list){
|
||||
list = list || clients;
|
||||
function ready() {
|
||||
if (list.len() >= n) {
|
||||
if (list.length >= n) {
|
||||
done();
|
||||
list.removeListener('add', ready);
|
||||
return true;
|
||||
@ -46,7 +48,7 @@ describe('PANIC!', function(){
|
||||
}
|
||||
}
|
||||
|
||||
function gunify(ctx, done){
|
||||
function gunify(done, ctx){
|
||||
var s = document.createElement('script');
|
||||
s.src = 'gun.js';
|
||||
s.onload = done;
|
||||
@ -69,7 +71,7 @@ describe('PANIC!', function(){
|
||||
var sync = gun.get('sync');
|
||||
sync.put({hello: 'world'})
|
||||
}).then(function(){
|
||||
return bob.run(function(ctx, done){
|
||||
return bob.run(function(done, ctx){
|
||||
var sync = gun.get('sync');
|
||||
sync.on(function(val){
|
||||
if(val.hello === 'world'){
|
177
test/holy/grail.js
Normal file
177
test/holy/grail.js
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
This file should be one
|
||||
folder deeper than every
|
||||
other file. It requires
|
||||
mocha to run.
|
||||
*/
|
||||
var panic = require('panic-server');
|
||||
var spawn = require('child_process').spawn;
|
||||
var path = require('path');
|
||||
var http = require('http');
|
||||
var fs = require('fs');
|
||||
var ports = require('./ports');
|
||||
|
||||
var wd = require('selenium-webdriver');
|
||||
|
||||
function open(url) {
|
||||
var driver = new wd.Builder()
|
||||
.forBrowser('firefox')
|
||||
.build();
|
||||
|
||||
driver.get(url);
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
open('http://localhost:' + ports.panic + '/index.html');
|
||||
open('http://localhost:' + ports.panic + '/index.html');
|
||||
|
||||
var staticServer = new http.Server(function (req, res) {
|
||||
if (req.url === '/') {
|
||||
req.url = '/index.html';
|
||||
}
|
||||
var file = path.join(__dirname, req.url);
|
||||
try {
|
||||
var page = fs.readFileSync(file, 'utf8');
|
||||
res.end(page);
|
||||
} catch (e) {
|
||||
// don't care
|
||||
}
|
||||
});
|
||||
|
||||
var server = panic.clients.filter('Node.js').pluck(1);
|
||||
var browsers = panic.clients.excluding(server);
|
||||
|
||||
var alice = browsers.pluck(1);
|
||||
var bob = browsers.excluding(alice).pluck(1);
|
||||
|
||||
var serverPath = path.join(__dirname, 'gun-server.js');
|
||||
|
||||
// start the server on :8080
|
||||
spawn('node', [serverPath]);
|
||||
|
||||
function waitFor (num, list) {
|
||||
return new Promise(function (res) {
|
||||
|
||||
function ready() {
|
||||
if (list.length < num) {
|
||||
return;
|
||||
}
|
||||
|
||||
res();
|
||||
list.removeListener('add', ready);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ready()) {
|
||||
list.on('add', ready);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
before(function () {
|
||||
|
||||
this.timeout(1500000);
|
||||
|
||||
// start the panic server
|
||||
panic.server(staticServer).listen(ports.panic);
|
||||
|
||||
return waitFor(2, browsers)
|
||||
.then(function () {
|
||||
return waitFor(1, server);
|
||||
});
|
||||
});
|
||||
|
||||
var scope = {
|
||||
uniqueKey: Math.random().toString(16).slice(2),
|
||||
file: path.join(process.cwd(), 'delete-me.json'),
|
||||
'@scope': true
|
||||
}
|
||||
|
||||
describe('The holy grail', function () {
|
||||
|
||||
it('should allow full recovery', function () {
|
||||
this.timeout(1500000);
|
||||
|
||||
return browsers.run(function () {
|
||||
localStorage.clear();
|
||||
})
|
||||
.then(function () {
|
||||
return browsers.run(function () {
|
||||
window.ref = gun.get(uniqueKey).put({
|
||||
text: 'ignore'
|
||||
});
|
||||
}, scope)
|
||||
})
|
||||
.then(function () {
|
||||
return alice.run(function (done) {
|
||||
// alice saves some data
|
||||
//ref.path('text').put('Initial text', done); // TODO: USE THIS LINE INSTEAD!
|
||||
ref.path('text').put('Initial text');
|
||||
setTimeout(done, 50);
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
return bob.run(function (done) {
|
||||
var ctx = this;
|
||||
ref.path('text').on(function (data) {
|
||||
if (data === 'ignore') {
|
||||
return;
|
||||
}
|
||||
// bob sees alice's data
|
||||
if (data !== 'Initial text') {
|
||||
ctx.fail('Wrong data showed up: ' + JSON.stringify(data));
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
return server.run(function () {
|
||||
var fs = require('fs');
|
||||
|
||||
// destroy the data
|
||||
fs.unlinkSync(file);
|
||||
|
||||
// crash the server
|
||||
process.exit(0);
|
||||
}, scope);
|
||||
})
|
||||
.then(function () {
|
||||
return alice.run(function (done) {
|
||||
ref.path('text').put('A conflicting update');
|
||||
setTimeout(done, 50);
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
return bob.run(function () {
|
||||
ref.path('text').put('B conflicting update');
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
spawn('node', [serverPath]);
|
||||
return waitFor(1, server);
|
||||
})
|
||||
.then(function () {
|
||||
return browsers.run(function (done) {
|
||||
var ctx = this;
|
||||
ref.path('text').on(function (value) {
|
||||
if (value === 'B conflicting update') {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
after(function () {
|
||||
if (server.length) {
|
||||
return server.run(function () {
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
});
|
16
test/holy/gun-server.js
Normal file
16
test/holy/gun-server.js
Normal file
@ -0,0 +1,16 @@
|
||||
var panic = require('panic-client');
|
||||
var ports = require('./ports');
|
||||
var Gun = require('gun');
|
||||
var gun = new Gun({
|
||||
file: 'delete-me.json'
|
||||
});
|
||||
|
||||
var http = require('http');
|
||||
|
||||
var server = new http.Server(gun.wsp.server);
|
||||
|
||||
gun.wsp(server);
|
||||
|
||||
server.listen(ports.gun);
|
||||
|
||||
panic.server('http://localhost:' + ports.panic);
|
27
test/holy/index.html
Normal file
27
test/holy/index.html
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Holy grail demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src='panic.js'></script>
|
||||
<script src='http://localhost:8080/gun.js'></script>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var req = new XMLHttpRequest();
|
||||
req.overrideMimeType('application/json');
|
||||
req.open('GET', 'ports.json');
|
||||
req.addEventListener('load', function () {
|
||||
var ports = JSON.parse(req.responseText);
|
||||
var server = 'http://localhost:' + ports.gun + '/gun';
|
||||
window.gun = new Gun(server);
|
||||
panic.server('http://localhost:' + ports.panic);
|
||||
});
|
||||
req.send();
|
||||
}());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
4
test/holy/ports.json
Normal file
4
test/holy/ports.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"panic": 3000,
|
||||
"gun": 8080
|
||||
}
|
@ -1978,11 +1978,13 @@
|
||||
var hewo = {hello: "world"};
|
||||
window.puti = window.puti || 0;
|
||||
window.geti = window.geti || 0;
|
||||
/*
|
||||
localStorage.clear();
|
||||
gun.get('users').put({1: {where: {lat: Math.random(), lng: Math.random(), i: 1}}});
|
||||
//var ok = function(a,b){ console.log('wat', a,b) }
|
||||
//Gun.log.debug=1;console.log("------------------");
|
||||
var val = gun.get('users').path(1).path('where').val(ok);
|
||||
*/
|
||||
});
|
||||
//localStorage.clear();
|
||||
/*
|
||||
|
@ -27,7 +27,7 @@
|
||||
<button id="abort">Abort</button>
|
||||
<button id="share">Share</button>
|
||||
<a id="share-result"></a>
|
||||
<script src="./mocha/json2.js"></script>
|
||||
<script src="../json2.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
|
||||
<script src="benchmark.js"></script>
|
||||
<script src="ptsd.js"></script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user