Merge branch 'pr/sirpy/9'

This commit is contained in:
Hadar Rottenberg 2020-01-13 12:52:39 +02:00
commit 761030d721
20 changed files with 1741 additions and 133 deletions

52
axe.js
View File

@ -60,6 +60,20 @@
// with one common superpeer (with ready failovers)
// in case the p2p linear latency is high.
// Or there could be plenty of other better options.
/*
AXE should have a couple of threshold items...
let's pretend there is a variable max peers connected
mob = 10000
if we get more peers than that...
we should start sending those peers a remote command
that they should connect to this or that other peer
and then once they (or before they do?) drop them from us.
sake of the test... gonna set that peer number to 1.
The mob threshold might be determined by other factors,
like how much RAM or CPU stress we have.
*/
opt.mob = opt.mob || Infinity;
var mesh = opt.mesh = opt.mesh || Gun.Mesh(at);
console.log("AXE enabled.");
@ -256,7 +270,7 @@
this.to.next(peer);
if(!peer.url){ return }
axe.up[peer.id] = peer;
})
});
at.on('bye', function(peer){ this.to.next(peer);
if(peer.url){ delete axe.up[peer.id] }
Gun.obj.map(peer.routes, function(route, hash){
@ -266,6 +280,42 @@
}
});
});
// handle rebalancing a mob of peers:
at.on('hi', function(peer){
this.to.next(peer);
if(peer.url){ return } // I am assuming that if we are wanting to make an outbound connection to them, that we don't ever want to drop them unless our actual config settings change.
var count = Object.keys(opt.peers).length;
if(opt.mob >= count){ return } // TODO: Make dynamic based on RAM/CPU also. Or possibly even weird stuff like opt.mob / axe.up length?
var peers = Object.keys(axe.up);
if(!peers.length){ return }
mesh.say({dam: 'mob', mob: count, peers: peers}, peer);
//setTimeout(function(){ mesh.bye(peer) }, 9); // something with better perf? // UNCOMMENT WHEN WE ACTIVATE THIS FEATURE
});
at.on('bye', function(peer){
this.to.next(peer);
});
at.on('hi', function(peer){
this.to.next(peer);
// this code handles disconnecting from self & duplicates
setTimeout(function(){ // must wait
if(peer.pid !== opt.pid){
// this extra logic checks for duplicate connections between 2 peers.
if(!Gun.obj.map(axe.up, function(p){
if(peer.pid === p.pid && peer !== p){
return yes = true;
}
})){ return }
}
mesh.say({dam: '-'}, peer);
delete at.dup.s[peer.last];
}, Math.random() * 100);
});
mesh.hear['-'] = function(msg, peer){
mesh.bye(peer);
peer.url = '';
}
}
function joindht(dht, soul, pids) {

View File

@ -31,12 +31,18 @@
<script src="../../gun/lib/monotype.js"></script>
<script src="../../gun/lib/meta.js"></script>
<script src="../../gun/lib/normalize.js"></script>
<script async src="../../gun/lib/fun.js"></script>
<script async src="../../gun/lib/wave.js"></script>
<!-- script async src="https://edide.io/music.lib"></script -->
<script>
var gun = Gun('https://guntest.herokuapp.com/gun');
var gun = Gun(['https://guntest.herokuapp.com/gun', 'http://localhost:8765/gun']);
;(window.onhashchange = function(){
var file = (location.hash||'').slice(1);
var S = +new Date;
$('#page').empty().attr('contenteditable', 'false');
gun.get('test/gun/docs/'+file).get('what').map().on(function render(data, i){
if(window.LOCK){ return }
var p = $('#page').children().get(i);
@ -50,15 +56,8 @@ var gun = Gun('https://guntest.herokuapp.com/gun');
p.outerHTML = safe;
r.restore();
});
return;
gun.get('test/gun/docs/'+file).get('what').once(function(data){
console.log(+new Date - S, 'ms load');
$('#page').html($.normalize(data));
});
})();
$("<textarea id='debug'>").css({position: 'fixed', height: '5em', width: '100%', bottom: 0, left: 0, 'font-size': '18pt'}).appendTo('body')
document.execCommand('defaultParagraphSeparator', false, 'p');
meta.edit({
name: "Edit",
@ -66,21 +65,18 @@ meta.edit({
use: function(eve){
console.log('on');
}, on: function(eve){
if($(eve.target).closest('p').length){ return }
var edit = this;
meta.flip(false);
var doc = $('#page').attr('contenteditable', 'true');
if(!doc.text()){
doc.html('<p class="loud crack"></p>');
edit.select(doc.children().first().get(0));
}
setTimeout(function(){ meta.flip(false) },1);
edit.init();
$(document).on('keydown.tmp', '[contenteditable]', function(eve){
if(eve.which != 13){ return }
eve.preventDefault();
var r = window.getSelection().getRangeAt(0);
var c = r.commonAncestorContainer;
var c = r.commonAncestorContainer, p;
r.deleteContents();
c.splitText(r.startOffset);
var p = $(c).parent(), n = $("<"+p.get(0).tagName+">"), f;
var p = c.splitText? $(c.splitText(r.startOffset)).parent() : $(c);
var n = $("<"+p.get(0).tagName+">"), f;
p.contents().each(function(){
if(this === c){ return f = true }
if(!f){ return }
@ -94,10 +90,13 @@ meta.edit({
edit.save(this);
});
}).on('keyup.tmp', '[contenteditable]', function(eve){
$('#debug').val(doc.html());
//$('#debug').val(doc.html());
var p = $(window.getSelection().anchorNode).closest('p');
var r = monotype(p);
var html = p.html() || '';
if(!html && !p.prev().length && !p.next().length && !$('#page').html()){
edit.init();
}
var safe = $.normalize(html);
p.html(safe);
r.restore();
@ -108,11 +107,19 @@ meta.edit({
console.log("UP");
$('[contenteditable=true]').off('.tmp');
},
init: function(){
var edit = this;
var doc = $('#page').attr('contenteditable', 'true');
if(!doc.text()){
doc.html('<p class="loud crack"></p>');
}
edit.select(doc.children().first().get(0));
},
save: function(p){
p = $(p);
var i = p.index();// = Array.prototype.indexOf.call(parent.children, child);
var file = (location.hash||'').slice(1);
var data = p.get(0).outerHTML;
var data = (p.get(0)||{}).outerHTML||'';
window.LOCK = true;
gun.get('test/gun/docs/'+file).get('what').get(i).put(data);
window.LOCK = false;
@ -135,18 +142,100 @@ meta.edit({
}
});
meta.edit({
name: "Save",
combo: ['S'], fake: -1,
on: function(eve){
return;
meta.tap.on.attr('contenteditable', 'false');
var what = $.normalize($('#page').html());
var file = (location.hash||'').slice(1);
gun.get('test/gun/docs/'+file).put({what: what});
},
up: function(){}
});
;(function(){
meta.edit({name: "Layout", combo: ['L']});
meta.edit({name: "Fill", combo: ['L','F'],
use: function(eve){},
on: function(eve){
var on = meta.tap();
meta.ask('Color name, code, or URL?', function(color){
on.css('background', color);
});
},
up: function(eve){}
});
meta.edit({name: "Add", combo: ['L','A']});
meta.edit({name: "Row", combo: ['L','A', 'R'],
on: function(eve){
meta.tap().append('<div style="min-height: 9em; padding: 2%;">');
}
});
meta.edit({name: "Columns", combo: ['L','A','C'],
on: function(eve){
var on = meta.tap().addClass('center'), tmp, c;
var html = '<div class="unit col" style="min-height: 9em; padding: 2%;"></div>';
if(!on.children('.col').length){ html += html }
c = (tmp = on.append(html).children('.col')).length;
tmp.each(function(){
$(this).css('width', (100/c)+'%');
})
}
});
meta.edit({name: "Text", combo: ['L','A','T'],
on: function(eve){
var tag = $('<p>text</p>');
meta.tap().append(tag);
tag.focus();
}
});
}());
;(function(){
var song = {};
// TODO:
// 1. Manually OR automatically load music.js API, dependencies, and modules. - FINE for now
// 2. only export music API, not meta, not dom, not mouselock system, not UI/html, etc. better module isolation and export.
// 3. `var wave = Wave('a').play()` // also on `Music.now`
// defaults... instrument: pure tones, volume curve: |\_ , speed curve: 0.5
// 4. `wave.blur(0.5).itch(0.5);`
// 5. wave.long(2); // how long in seconds each note plays, optionally: wave.pace(60) is bpm
// 6. wave.loud(0.5); // 0% to 100% volume loudness of device output.
// 7. wave.vary(0.5); // slows down or speeds up wiggle per harmonic
// 8:
// wave structure, does ToneJS allow us to change the sine wave smoothness/type continuously or is it a pre-fixed type?
// wave structure: /\/\/, |_|, /|/, \|\| do some research with ToneJS whether these are dynamic or fixed
// wave.itch(); // changes the shape of the wiggle from smooth sine to square or triangle
// wave.blur(220hz); // blur may not apply/work on pure notes other than filtering them.
meta.edit({name: "Music", combo: ['M']});
meta.edit({name: "Play", combo: ['M','P'],
on: function(eve){
// TODO: We still need to add to meta API ability to change name.
if(song.play){
music.stop();
song.play = false;
return;
}
song.play = true;
music.stop();
setTimeout(function(){
song.now = wave($('#page').text()).play();
},250);
}
});
meta.edit({name: "Blur", combo: ['M','B'],
on: function(eve){
$(document).on('mousemove.tmp', function(eve){
var x = eve.pageX;
song.now.loud(x/$('body').innerWidth());
});
},
up: function(){
$(document).off('.tmp');
}
});
$(document).on('keydown', function(eve){
music.play(String.fromCharCode(eve.which));
});
}());
</script>
</body>
</html>

View File

@ -1,3 +1,4 @@
<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
@ -35,4 +36,4 @@
ReactDOM.render(<App />, document.getElementById("app"));
</script>
</body>
</html>
</html>

View File

@ -53,6 +53,10 @@
$('#hours').text((data.up.time / 60 / 60).toFixed(0));
Stats('memory').line.append(+new Date, data.memory.heapTotal / 1024 / 1024);
try{ Stats('dam # in').line.append(+new Date, data.dam.in.count); }catch(e){}
try{ Stats('dam in MB').line.append(+new Date, data.dam.in.done / 1024 / 1024); }catch(e){}
try{ Stats('dam # out').line.append(+new Date, data.dam.out.count); }catch(e){}
try{ Stats('dam out MB').line.append(+new Date, data.dam.out.done / 1024 / 1024); }catch(e){}
console.log('data',data);
//fetch keys in all, these may be dynamically changing

23
gun.js
View File

@ -961,7 +961,7 @@
if(obj_has(back, 'put')){
back.on('in', back);
}
if(tmp){ return }
if(tmp && u !== back.put){ return } //if(tmp){ return }
msg.$ = back.$;
} else
if(obj_has(back.put, get)){ // TODO: support #LEX !
@ -1174,7 +1174,7 @@
if(u === tmp && u !== at.put){ return true }
neat.put = u;
if(neat.ack){
neat.ack = -1; // TODO: BUG? Should this be 0?
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,
@ -2122,7 +2122,8 @@
opt.peers[peer.url || peer.id] = peer;
} else {
tmp = peer.id = peer.id || Type.text.random(9);
mesh.say({dam: '?'}, opt.peers[tmp] = peer);
mesh.say({dam: '?', pid: root.opt.pid}, opt.peers[tmp] = peer);
delete dup.s[peer.last]; // IMPORTANT: see https://gun.eco/docs/DAM#self
}
peer.met = peer.met || +(new Date);
if(!tmp.hied){ root.on(tmp.hied = 'hi', peer) }
@ -2140,18 +2141,12 @@
}
mesh.hear['!'] = function(msg, peer){ opt.log('Error:', msg.err) }
mesh.hear['?'] = function(msg, peer){
if(!msg.pid){
mesh.say({dam: '?', pid: opt.pid, '@': msg['#']}, peer);
// @rogowski I want to re-enable this AXE logic with some fix/merge later.
/* var tmp = peer.queue; peer.queue = [];
Type.obj.map(tmp, function(msg){
mesh.say(msg, peer);
}); */
// @rogowski 2: I think with my PID fix we can delete this and use the original.
return;
if(msg.pid){
if(!peer.pid){ peer.pid = msg.pid }
if(msg['@']){ return }
}
if(peer.pid){ return }
peer.pid = msg.pid;
mesh.say({dam: '?', pid: opt.pid, '@': msg['#']}, peer);
delete dup.s[peer.last]; // IMPORTANT: see https://gun.eco/docs/DAM#self
}
root.on('create', function(root){

2
gun.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -17,6 +17,7 @@
/* UNBUILD */
;USE(function(module){
var noop = function(){}, u;
$.fn.or = function(s){ return this.length ? this : $(s||'body') };
var m = window.meta = {edit:[]};
@ -30,19 +31,18 @@
var key = (k.eve = m.eve = eve).which = eve.which || eve.fake || eve.keyCode;
// ADDED
if(!m.flip.is() && !k.meta[key]){ return } // cancel non-open events when closed TODO make optional
//if(!m.flip.is() && !k.meta[key]){ return } // cancel non-open events when closed TODO make optional
if(!k.meta[key] && withMeta(eve) && !k.at[key]) { return m.flip(false) } // cancel and close when no action and "meta key" held down (e.g. ctrl+c)
if(!eve.fake && key === k.last){ return }; k.last = key; // jussi: polyfilling eve.repeat?
if(!eve.fake && $(eve.target).closest('input, textarea, [contenteditable=true]').length){
// if(k.meta[key]){ k.down.meta = key = -1 }
// if(!k.down.meta){ return }
// prevent typing with meta open
if(meta.flip.is() && !withMeta(eve)) eve.preventDefault()
if(!eve.fake && $(eve.target).closest('input, textarea, [contenteditable=true]').length && !$(eve.target).closest('#meta').length){
if(!meta.flip.is() && !withMeta(eve)){ // cancel meta/hud during text input UNLESS hud is open OR cmd key is held down.
return;
}
//if(k.meta[key]){ k.down.meta = key = -1 }
//if(!k.down.meta){ return }
// hmmm?
// if(!k.meta[key] && !meta.flip.is()) return // aserwed
//if(!k.meta[key] && !meta.flip.is()) return // aserwed
}
m.check('on', key, k.at || (k.at = m.edit));
if(k.meta[key]){
@ -53,7 +53,7 @@
}
k.up = function(eve){ var tmp;
var key = (k.eve = m.eve = eve).which = eve.which || eve.fake || eve.keyCode;
if(!m.flip.is() && !k.meta[key]){ return } // ADDED cancel non-open events when closed TODO make optional
//if(!m.flip.is() && !k.meta[key]){ return } // ADDED cancel non-open events when closed TODO make optional
// if(!eve.fake && $(eve.target).closest('input, textarea, [contenteditable=true]').length){
// if(k.meta[key]){
// k.down.meta = null;
@ -131,7 +131,8 @@
eve.preventDefault();
cb($put.val());
$li.remove();
k.wipe();
//k.wipe();
m.list(k.at);
});
var $li = $('<li>').append($form);
$ul.append($li);
@ -147,7 +148,7 @@
m.tap = function(){
var on = $('.meta-on')
.or($($(document.querySelectorAll(':hover')).get().reverse()).first())
.or($(document.elementFromPoint(meta.tap.x, meta.tap.y)));
.or($(document.elementFromPoint(meta.tap.x||0, meta.tap.y||0)));
return on;
}
meta.edit = function(edit){
@ -167,18 +168,18 @@
;USE(function(module){
/* UI */
meta.ui = {
blink: function(){ // hint visually that action has happened
blink: function(){ // hint visually that action has happened
$('#meta').css('transition', 'none').css('background', 'none')
setTimeout(function(){
$('#meta')[0].style.transition = null
$('#meta')[0].style.background = null
$('#meta')[0].style.transition = null
$('#meta')[0].style.background = null
})
},
depth: function(n){
if (n) {
$('#meta').css('background', 'hsl(60, 100%,'+(85-(n*10))+'%)');
$('#meta').css('background', 'hsl(60, 100%,'+(85-(n*10))+'%)');
} else {
$('#meta')[0].style.background = null
$('#meta')[0].style.background = null
}
}
}
@ -236,7 +237,8 @@
'border-radius': '1em',
'margin-left': '0.25em',
'margin-top': '0.25em',
'float': 'right'
'float': 'right',
'cursor': 'pointer'
},
'#meta a': {color: 'black'},
// '#meta:hover': {opacity: 1},
@ -274,6 +276,7 @@
})(USE, './metaUI');
;USE(function(module){
// include basic text editing by default.
var monotype = window.monotype || function(){console.log("monotype needed")};
var m = meta;
@ -420,13 +423,13 @@
})(USE, './metaText');
;USE(function(module){
var m = meta, k = m.key;
$(window).on('blur', k.wipe.bind(null, false)).on('focus', k.wipe.bind(null, false));
//$(document).on('mousedown mousemove mouseup', function(eve){
// m.tap.eve = eve;
// m.tap.x = eve.pageX||0;
// m.tap.y = eve.pageY||0;
// m.tap.on = $(eve.target);
//})
$(window).on('focus', k.wipe.bind(null, false)); // .on('blur', k.wipe.bind(null, false))
$(document).on('mousedown mousemove mouseup', function(eve){
m.tap.eve = eve;
m.tap.x = eve.pageX||0;
m.tap.y = eve.pageY||0;
m.tap.on = $(eve.target);
})
// Setting m.tap.edit has been commented, so should never end up here?
//.on('mousedown touchstart', function(eve){
// var tmp = m.tap.edit;
@ -437,12 +440,17 @@
//$(document).on('touchstart', '#meta .meta-start', function(eve){ m.tap.stun = true });
$(document).on('click', '#meta .meta-menu li', function(eve){
var combo = $(this).data().combo;
eve.fake = eve.which = combo && combo.slice(-1)[0].charCodeAt(0);
var [start, end] = 'ontouchstart' in window
? ['touchstart', 'touchend']
: ['mousedown', 'mouseup']
$(document).on(start, '#meta .meta-menu li', function(eve){
var combo = $(this).data().combo;
eve.fake = eve.which = combo && combo.slice(-1)[0].charCodeAt(0);
eve.tap = true;
k.down(eve); k.up(eve);
return;
k.down(eve);
$(document).one(end, () => k.up(eve))
return;
// if(m.tap.stun){ return m.tap.stun = false }
// if(!(eve.fake = eve.which = (($(this).text().match(/[A-Z]/)||{})[0]||'').toUpperCase().charCodeAt(0))){ return }
// eve.tap = true;
@ -451,6 +459,11 @@
});
$(document).on('keydown', k.down).on('keyup', k.up);
$('#meta').on('click', function(ev) {
if (ev.target.tagName == 'LI' || ev.target.tagName == 'UL') return
meta.flip()
})
//$(document).on('select contextmenu keyup mouseup', '[contenteditable=true]', m.text.on);

View File

@ -22,7 +22,7 @@ Gun.on('create', function(root){
socket.bind({port: udp.port, exclusive: true}, function(){
socket.setBroadcast(true);
socket.setMulticastTTL(128);
socket.addMembership(udp.address);
try{ socket.addMembership(udp.address); }catch(e){}
});
socket.on("listening", function(){

View File

@ -5,6 +5,7 @@ Gun.chain.open = function(cb, opt, at){
opt.doc = opt.doc || {};
opt.ids = opt.ids || {};
opt.any = opt.any || cb;
opt.meta = opt.meta || false;
opt.ev = opt.ev || {off: function(){
Gun.obj.map(opt.ev.s, function(e){
if(e){ e.off() }
@ -12,7 +13,9 @@ Gun.chain.open = function(cb, opt, at){
opt.ev.s = {};
}, s:{}}
return this.on(function(data, key, ctx, ev){
delete ((data = Gun.obj.copy(data))||{})._;
if(opt.meta !== true){
delete ((data = Gun.obj.copy(data))||{})._;
}
clearTimeout(opt.to);
opt.to = setTimeout(function(){
if(!opt.any){ return }

View File

@ -2,6 +2,7 @@
var Gun = require('../gun'), u;
Gun.serve = require('./serve');
//process.env.GUN_ENV = process.env.GUN_ENV || 'debug';
//console.LOG = true; // only temporarily, REVERT THIS IN FUTURE!
Gun.on('opt', function(root){
if(u === root.opt.super){
root.opt.super = true;

View File

@ -66,7 +66,7 @@ Gun.log = function(a,b,c,d){
if('number' == typeof a && 'number' == typeof b && 'string' == typeof c){
var tmp = (all[c] || (all[c] = []));
if(max < tmp.push([a,b])){ all[c] = [] } // reset
return;
//return;
}
return log.apply(Gun, arguments);
}

1242
lib/wave.js Normal file

File diff suppressed because it is too large Load Diff

13
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "gun",
"version": "0.2019.915",
"version": "0.2019.1211",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -40,7 +40,8 @@
"@types/node": {
"version": "10.14.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.18.tgz",
"integrity": "sha512-ryO3Q3++yZC/+b8j8BdKd/dn9JlzlHBPdm80656xwYUdmPkpTGTjkAdt6BByiNupGPE8w0FhBgvYy/fX9hRNGQ=="
"integrity": "sha512-ryO3Q3++yZC/+b8j8BdKd/dn9JlzlHBPdm80656xwYUdmPkpTGTjkAdt6BByiNupGPE8w0FhBgvYy/fX9hRNGQ==",
"optional": true
},
"@unimodules/core": {
"version": "3.0.2",
@ -120,6 +121,7 @@
"version": "2.0.26",
"resolved": "https://registry.npmjs.org/asn1js/-/asn1js-2.0.26.tgz",
"integrity": "sha512-yG89F0j9B4B0MKIcFyWWxnpZPLaNTjCj4tkE3fjbAoo0qmpGw0PYYqSbX/4ebnd9Icn8ZgK4K1fvDyEtW1JYtQ==",
"optional": true,
"requires": {
"pvutils": "^1.0.17"
}
@ -1347,6 +1349,7 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.0.6.tgz",
"integrity": "sha512-0yNrOdJyLE7FZzmeEHTKanwBr5XbmDAd020cKa4ZiTYuGMBYBZmq7vHOhcOqhVllh6gghDBbaz1lnVdOqiB7cw==",
"optional": true,
"requires": {
"@types/node": "^10.14.17",
"tslib": "^1.10.0"
@ -1355,7 +1358,8 @@
"pvutils": {
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.0.17.tgz",
"integrity": "sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ=="
"integrity": "sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==",
"optional": true
},
"querystring": {
"version": "0.2.0",
@ -1664,7 +1668,8 @@
"tslib": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
"optional": true
},
"uglify-js": {
"version": "3.6.0",

View File

@ -1,6 +1,6 @@
{
"name": "gun",
"version": "0.2019.1120",
"version": "0.2019.1228",
"description": "A realtime, decentralized, offline-first, graph data synchronization engine.",
"main": "index.js",
"browser": "browser.js",

4
sea.js
View File

@ -191,8 +191,8 @@
const isocrypto = require('isomorphic-webcrypto');
api.ossl = api.subtle = isocrypto.subtle;
}catch(e){
console.log("node-webcrypto-ossl and text-encoding may not be included by default, please add it to your package.json!");
OSSL_WEBCRYPTO_OR_TEXT_ENCODING_NOT_INSTALLED;
console.log("text-encoding and @peculiar/webcrypto may not be included by default, please add it to your package.json!");
TEXT_ENCODING_OR_PECULIAR_WEBCRYPTO_NOT_INSTALLED;
}}
module.exports = api

View File

@ -19,14 +19,14 @@ function Mesh(root){
if('[' === tmp){
try{msg = JSON.parse(raw);}catch(e){opt.log('DAM JSON parse error', e)}
if(!msg){ return }
LOG && opt.log(msg.length, 'in hear batch');
LOG && opt.log(+new Date, msg.length, 'in hear batch');
(function go(){
var S; LOG && (S = +new Date); // STATS!
var m, c = 100; // hardcoded for now?
while(c-- && (m = msg.shift())){
mesh.hear(m, peer);
}
LOG && opt.log(+new Date - S, 'batch heard');
LOG && opt.log(S, +new Date - S, 'batch heard');
if(!msg.length){ return }
puff(go, 0);
}());
@ -55,7 +55,7 @@ function Mesh(root){
}
var S; LOG && (S = +new Date);
root.on('in', msg);
LOG && !msg.nts && opt.log(+new Date - S, 'msg', msg['#']);
LOG && !msg.nts && opt.log(S, +new Date - S, 'msg', msg['#']);
return;
}
}
@ -83,7 +83,7 @@ function Mesh(root){
}
}
}
LOG && opt.log(+new Date - S, 'say prep');
LOG && opt.log(S, +new Date - S, 'say prep');
dup.track(id).it = msg; // track for 9 seconds, default. Earth<->Mars would need more!
if(!peer){ peer = (tmp = dup.s[msg['@']]) && (tmp = tmp.it) && (tmp = tmp._) && (tmp = tmp.via) }
if(!peer && mesh.way){ return mesh.way(msg) }
@ -91,7 +91,7 @@ function Mesh(root){
if(!Type.obj.is(peer || opt.peers)){ return false }
var S; LOG && (S = +new Date);
Type.obj.map(peer || opt.peers, each); // in case peer is a peer list.
LOG && opt.log(+new Date - S, 'say loop');
LOG && opt.log(S, +new Date - S, 'say loop');
return;
}
if(!peer.wire && mesh.wire){ mesh.wire(peer) }
@ -118,7 +118,7 @@ function Mesh(root){
var S; LOG && (S = +new Date);
try{tmp = (1 === tmp.length? tmp[0] : JSON.stringify(tmp));
}catch(e){return opt.log('DAM JSON stringify error', e)}
LOG && opt.log(+new Date - S, 'say stringify', tmp.length);
LOG && opt.log(S, +new Date - S, 'say stringify', tmp.length);
if(!tmp){ return }
send(tmp, peer);
}
@ -135,7 +135,7 @@ function Mesh(root){
if(wire.send){
wire.send(raw);
}
LOG && opt.log(+new Date - S, 'wire send', raw.length);
LOG && opt.log(S, +new Date - S, 'wire send', raw.length);
mesh.say.d += raw.length||0; ++mesh.say.c; // STATS!
}catch(e){
(peer.queue = peer.queue || []).push(raw);
@ -171,7 +171,8 @@ function Mesh(root){
opt.peers[peer.url || peer.id] = peer;
} else {
tmp = peer.id = peer.id || Type.text.random(9);
mesh.say({dam: '?'}, opt.peers[tmp] = peer);
mesh.say({dam: '?', pid: root.opt.pid}, opt.peers[tmp] = peer);
delete dup.s[peer.last]; // IMPORTANT: see https://gun.eco/docs/DAM#self
}
peer.met = peer.met || +(new Date);
if(!tmp.hied){ root.on(tmp.hied = 'hi', peer) }
@ -189,18 +190,12 @@ function Mesh(root){
}
mesh.hear['!'] = function(msg, peer){ opt.log('Error:', msg.err) }
mesh.hear['?'] = function(msg, peer){
if(!msg.pid){
mesh.say({dam: '?', pid: opt.pid, '@': msg['#']}, peer);
// @rogowski I want to re-enable this AXE logic with some fix/merge later.
/* var tmp = peer.queue; peer.queue = [];
Type.obj.map(tmp, function(msg){
mesh.say(msg, peer);
}); */
// @rogowski 2: I think with my PID fix we can delete this and use the original.
return;
if(msg.pid){
if(!peer.pid){ peer.pid = msg.pid }
if(msg['@']){ return }
}
if(peer.pid){ return }
peer.pid = msg.pid;
mesh.say({dam: '?', pid: opt.pid, '@': msg['#']}, peer);
delete dup.s[peer.last]; // IMPORTANT: see https://gun.eco/docs/DAM#self
}
root.on('create', function(root){

View File

@ -34,7 +34,7 @@ function output(msg){
if(obj_has(back, 'put')){
back.on('in', back);
}
if(tmp){ return }
if(tmp && u !== back.put){ return } //if(tmp){ return }
msg.$ = back.$;
} else
if(obj_has(back.put, get)){ // TODO: support #LEX !
@ -247,7 +247,7 @@ function not(at, msg){
if(u === tmp && u !== at.put){ return true }
neat.put = u;
if(neat.ack){
neat.ack = -1; // TODO: BUG? Should this be 0?
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,

View File

@ -3774,6 +3774,24 @@ describe('Gun', function(){
done();
})
});
/*describe('talk to live server tests', function(){
this.timeout(1000 * 9);
it.only('Second once on undefined should call', function(done){ // this test is passing when it fails by hand?
var gun = Gun('https://gunjs.herokuapp.com/gun');
gun.get('~@O8H2BJa4pNfecWamWN7efd888Pg1@hackernoon').once(function(data){
console.log(1, data);
expect(data).to.not.be.ok();
setTimeout(function(){
gun.get('~@O8H2BJa4pNfecWamWN7efd888Pg1@hackernoon').once(function(data){
console.log(2, data);
expect(data).to.not.be.ok();
done();
});
}, 3000);
});
});
});*/
return;
it('Nested listener should be called', function(done){

View File

@ -2,13 +2,51 @@
This is the first in a series of basic networking correctness tests.
Each test itself might be dumb and simple, but built up together,
they prove desired end goals for behavior at scale.
Alice: [Bob]
Bob: [Carl]
Carl: [Bob]
Dave: [Carl]
Ed: [?]
100,000 browsers
1 relay peer
50,000 browsers on Bob
50,000 browsers on Carl
//var gun = Gun(['https://gunjs.herokuapp.com/gun', 'https://guntest.herokuapp.com/gun']);
pretend we have 3TB of data.
300K browsers.
suppose we have 3 nodejs peers that are shards
var superpeer1 = Gun(AXE({shard: 'a~m'}));
var superpeer2 = Gun(AXE({shard: 'n~r'}));
var superpeer3 = Gun(AXE({shard: 's~z'}));
300K browsers join a popular app and they have to do this
via the browser, so they all go to superpeer1.com
then 2/3 of them should get sharded to superpeer2 & superpeer3
first all connect to:
..s1-----s2--s3
./\.\.
b1.b2.b3
then be load balanced to:
..s1--s2--s3
./....|....\.
b1....b2....b3
*/
var config = {
IP: require('ip').address(),
port: 8765,
servers: 2,
browsers: 2,
servers: 3,
browsers: 3,
route: {
'/': __dirname + '/index.html',
'/gun.js': __dirname + '/../../gun.js',
@ -35,11 +73,15 @@ manager.start({
});
var servers = clients.filter('Node.js');
var bob = servers.pluck(1);
var carl = servers.excluding(bob).pluck(1);
var s1 = servers.pluck(1);
var s2 = servers.excluding(s1).pluck(1);
var s3 = servers.excluding([s1,s2]).pluck(1);
var browsers = clients.excluding(servers);
var alice = browsers.pluck(1);
var dave = browsers.excluding(alice).pluck(1);
var b1 = browsers.pluck(1);
var b2 = servers.excluding(b1).pluck(1);
var b3 = servers.excluding([b1,b2]).pluck(1);
describe("Put ACK", function(){
//this.timeout(5 * 60 * 1000);
@ -65,12 +107,13 @@ describe("Put ACK", function(){
var peers = [], i = env.config.servers;
while(i--){
var tmp = (env.config.port + (i + 1));
if(port != tmp){ // ignore ourselves
//if(port != tmp){ // ignore ourselves
peers.push('http://'+ env.config.IP + ':' + tmp + '/gun');
}
//}
}
console.log(port, " connect to ", peers);
var gun = Gun({file: env.i+'data', peers: peers, web: server});
var gun = Gun({file: env.i+'data', peers: peers, web: server, mob: 4});
global.gun = gun;
server.listen(port, function(){
test.done();
});
@ -85,13 +128,29 @@ describe("Put ACK", function(){
});
it("Browsers initialized gun!", function(){
var tests = [], i = 1;
browsers.each(function(client, id){
tests.push(client.run(function(test){
var tests = [], i = 0;
browsers.each(function(browser, id){
tests.push(browser.run(function(test){
try{ localStorage.clear() }catch(e){}
try{ indexedDB.deleteDatabase('radata') }catch(e){}
var env = test.props;
var gun = Gun('http://'+ env.config.IP + ':' + (env.config.port + 1) + '/gun');
var mesh = gun.back('opt.mesh');
mesh.hear['mob'] = function(msg, peer){
// TODO: NOTE, code AXE DHT to aggressively drop new peers AFTER superpeer sends this rebalance/disconnect message that contains some other superpeers.
if(!msg.peers){ return }
var one = msg.peers[Math.floor(Math.random()*msg.peers.length)];
console.log("CONNECT TO THIS PEER:", one);
gun.opt(one);
mesh.bye(peer);
if(test.c){ return }
test.c = 1;
test.done();
}
console.log("connected to who superpeer(s)?", gun._.opt.peers);
window.gun = gun;
window.ref = gun.get('test');
}, {i: i += 1, config: config}));
@ -99,20 +158,16 @@ describe("Put ACK", function(){
return Promise.all(tests);
});
it("Alice", function(){
return alice.run(function(test){
console.log("I AM ALICE");
//test.async();
console.log(gun._.opt.peers);
});
});
it("Got Load Balanced to Different Peer", function(){
var tests = [], i = 0;
browsers.each(function(browser, id){
tests.push(browser.run(function(test){
it("Dave", function(){
return dave.run(function(test){
console.log("I AM DAVE");
//test.async();
console.log(gun._.opt.peers);
console.log("...", gun._.opt.peers);
}, {i: i += 1, config: config}));
});
return Promise.all(tests);
});
it("All finished!", function(done){

137
test/panic/bulkimport.js Normal file
View File

@ -0,0 +1,137 @@
/*
This is the first in a series of basic networking correctness tests.
Each test itself might be dumb and simple, but built up together,
they prove desired end goals for behavior at scale.
1. (this file) Is a browser write is confirmed as save by multiple peers even if by daisy chain.
2.
*/
var config = {
IP: require('ip').address(),
port: 8765,
servers: 1,
browsers: 2,
puts: 1000,
route: {
'/': __dirname + '/index.html',
'/gun.js': __dirname + '/../../gun.js',
'/jquery.js': __dirname + '/../../examples/jquery.js'
}
}
var panic = require('panic-server');
panic.server().on('request', function(req, res){
config.route[req.url] && require('fs').createReadStream(config.route[req.url]).pipe(res);
}).listen(config.port);
var clients = panic.clients;
var manager = require('panic-manager')();
manager.start({
clients: Array(config.servers).fill().map(function(u, i){
return {
type: 'node',
port: config.port + (i + 1)
}
}),
panic: 'http://' + config.IP + ':' + config.port
});
var servers = clients.filter('Node.js');
var bob = servers.pluck(1);
var browsers = clients.excluding(servers);
var alice = browsers.pluck(1);
var carl = browsers.excluding(alice).pluck(1);
describe("Put ACK", function(){
//this.timeout(5 * 60 * 1000);
this.timeout(10 * 60 * 1000);
it("Servers have joined!", function(){
return servers.atLeast(config.servers);
});
it("GUN started!", function(){
var tests = [], i = 0;
servers.each(function(client){
tests.push(client.run(function(test){
var env = test.props;
test.async();
try{ require('fs').unlinkSync(env.i+'data') }catch(e){}
try{ require('gun/lib/fsrm')(env.i+'data') }catch(e){}
var server = require('http').createServer(function(req, res){
res.end("I am "+ env.i +"!");
});
var port = env.config.port + env.i;
var Gun = require('gun');
var peers = [], i = env.config.servers;
while(i--){
var tmp = (env.config.port + (i + 1));
if(port != tmp){ // ignore ourselves
peers.push('http://'+ env.config.IP + ':' + tmp + '/gun');
}
}
console.log(port, " connect to ", peers);
var gun = Gun({file: env.i+'data', peers: peers, web: server});
server.listen(port, function(){
test.done();
});
}, {i: i += 1, config: config}));
});
return Promise.all(tests);
});
it(config.browsers +" browser(s) have joined!", function(){
console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!");
return browsers.atLeast(config.browsers);
});
it("Browsers initialized gun!", function(){
var tests = [], i = 0;
browsers.each(function(client, id){
tests.push(client.run(function(test){
try{ localStorage.clear() }catch(e){}
try{ indexedDB.deleteDatabase('radata') }catch(e){}
var env = test.props;
var gun = Gun('http://'+ env.config.IP + ':' + (env.config.port + 1) + '/gun');
window.ref = gun.get('test');
}, {i: i += 1, config: config}));
});
return Promise.all(tests);
});
it("Puts", function(){
return alice.run(function(test){
console.log("I AM ALICE");
test.async();
var i = test.props.puts, d = 0;
while(i--){ go(i) }
function go(i){
ref.get(i).put({hello: 'world'}, function(ack){
if(ack.err){ put_failed }
if(++d !== test.props.puts){ return }
console.log("all success", d);
test.done();
});
}
}, {puts: config.puts});
});
it("All finished!", function(done){
console.log("Done! Cleaning things up...");
setTimeout(function(){
done();
},1000);
});
after("Everything shut down.", function(){
browsers.run(function(){
//location.reload();
//setTimeout(function(){
//}, 15 * 1000);
});
return servers.run(function(){
process.exit();
});
});
});